Tue Apr 14 18:34:29 2015 UTC ()
Add a new SDHC_FLAG, SDHC_FLAG_EXTDMA_DMAEN, which request that the
SDHC_DMA_ENABLE bit be set in the command, even if we're using an
external DMA engine. Needed by the upcoming DMA support for AM335x
(beaglebone).


(bouyer)
diff -r1.54 -r1.55 src/sys/dev/sdmmc/sdhc.c
diff -r1.15 -r1.16 src/sys/dev/sdmmc/sdhcvar.h

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

--- src/sys/dev/sdmmc/sdhc.c 2015/02/27 15:53:09 1.54
+++ src/sys/dev/sdmmc/sdhc.c 2015/04/14 18:34:29 1.55
@@ -1,39 +1,39 @@ @@ -1,39 +1,39 @@
1/* $NetBSD: sdhc.c,v 1.54 2015/02/27 15:53:09 nonaka Exp $ */ 1/* $NetBSD: sdhc.c,v 1.55 2015/04/14 18:34:29 bouyer 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.54 2015/02/27 15:53:09 nonaka Exp $"); 26__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.55 2015/04/14 18:34:29 bouyer 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>
@@ -76,26 +76,27 @@ struct sdhc_host { @@ -76,26 +76,27 @@ struct sdhc_host {
76 uint8_t regs[14]; /* host controller state */ 76 uint8_t regs[14]; /* host controller state */
77 77
78 uint16_t intr_status; /* soft interrupt status */ 78 uint16_t intr_status; /* soft interrupt status */
79 uint16_t intr_error_status; /* soft error status */ 79 uint16_t intr_error_status; /* soft error status */
80 struct kmutex intr_mtx; 80 struct kmutex intr_mtx;
81 struct kcondvar intr_cv; 81 struct kcondvar intr_cv;
82 82
83 int specver; /* spec. version */ 83 int specver; /* spec. version */
84 84
85 uint32_t flags; /* flags for this host */ 85 uint32_t flags; /* flags for this host */
86#define SHF_USE_DMA 0x0001 86#define SHF_USE_DMA 0x0001
87#define SHF_USE_4BIT_MODE 0x0002 87#define SHF_USE_4BIT_MODE 0x0002
88#define SHF_USE_8BIT_MODE 0x0004 88#define SHF_USE_8BIT_MODE 0x0004
 89#define SHF_MODE_DMAEN 0x0008 /* needs SDHC_DMA_ENABLE in mode */
89}; 90};
90 91
91#define HDEVNAME(hp) (device_xname((hp)->sc->sc_dev)) 92#define HDEVNAME(hp) (device_xname((hp)->sc->sc_dev))
92 93
93static uint8_t 94static uint8_t
94hread1(struct sdhc_host *hp, bus_size_t reg) 95hread1(struct sdhc_host *hp, bus_size_t reg)
95{ 96{
96 97
97 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) 98 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
98 return bus_space_read_1(hp->iot, hp->ioh, reg); 99 return bus_space_read_1(hp->iot, hp->ioh, reg);
99 return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 3)); 100 return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 3));
100} 101}
101 102
@@ -299,31 +300,39 @@ sdhc_host_found(struct sdhc_softc *sc, b @@ -299,31 +300,39 @@ sdhc_host_found(struct sdhc_softc *sc, b
299 * Reset the host controller and enable interrupts. 300 * Reset the host controller and enable interrupts.
300 */ 301 */
301 (void)sdhc_host_reset(hp); 302 (void)sdhc_host_reset(hp);
302 303
303 /* Determine host capabilities. */ 304 /* Determine host capabilities. */
304 if (ISSET(sc->sc_flags, SDHC_FLAG_HOSTCAPS)) { 305 if (ISSET(sc->sc_flags, SDHC_FLAG_HOSTCAPS)) {
305 caps = sc->sc_caps; 306 caps = sc->sc_caps;
306 } else { 307 } else {
307 mutex_enter(&hp->host_mtx); 308 mutex_enter(&hp->host_mtx);
308 caps = HREAD4(hp, SDHC_CAPABILITIES); 309 caps = HREAD4(hp, SDHC_CAPABILITIES);
309 mutex_exit(&hp->host_mtx); 310 mutex_exit(&hp->host_mtx);
310 } 311 }
311 312
312 /* Use DMA if the host system and the controller support it. */ 313 /*
 314 * Use DMA if the host system and the controller support it.
 315 * Suports integrated or external DMA egine, with or without
 316 * SDHC_DMA_ENABLE in the command.
 317 */
313 if (ISSET(sc->sc_flags, SDHC_FLAG_FORCE_DMA) || 318 if (ISSET(sc->sc_flags, SDHC_FLAG_FORCE_DMA) ||
314 (ISSET(sc->sc_flags, SDHC_FLAG_USE_DMA && 319 (ISSET(sc->sc_flags, SDHC_FLAG_USE_DMA &&
315 ISSET(caps, SDHC_DMA_SUPPORT)))) { 320 ISSET(caps, SDHC_DMA_SUPPORT)))) {
316 SET(hp->flags, SHF_USE_DMA); 321 SET(hp->flags, SHF_USE_DMA);
 322 if (!ISSET(sc->sc_flags, SDHC_FLAG_EXTERNAL_DMA) ||
 323 ISSET(sc->sc_flags, SDHC_FLAG_EXTDMA_DMAEN))
 324 SET(hp->flags, SHF_MODE_DMAEN);
 325
317 aprint_normal_dev(sc->sc_dev, "using DMA transfer\n"); 326 aprint_normal_dev(sc->sc_dev, "using DMA transfer\n");
318 } 327 }
319 328
320 /* 329 /*
321 * Determine the base clock frequency. (2.2.24) 330 * Determine the base clock frequency. (2.2.24)
322 */ 331 */
323 if (hp->specver == SDHC_SPEC_VERS_300) { 332 if (hp->specver == SDHC_SPEC_VERS_300) {
324 hp->clkbase = SDHC_BASE_V3_FREQ_KHZ(caps); 333 hp->clkbase = SDHC_BASE_V3_FREQ_KHZ(caps);
325 } else { 334 } else {
326 hp->clkbase = SDHC_BASE_FREQ_KHZ(caps); 335 hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
327 } 336 }
328 if (hp->clkbase == 0) { 337 if (hp->clkbase == 0) {
329 if (sc->sc_clkbase == 0) { 338 if (sc->sc_clkbase == 0) {
@@ -1195,27 +1204,27 @@ sdhc_start_command(struct sdhc_host *hp, @@ -1195,27 +1204,27 @@ sdhc_start_command(struct sdhc_host *hp,
1195 return EINVAL; 1204 return EINVAL;
1196 } 1205 }
1197 1206
1198 /* Prepare transfer mode register value. (2.2.5) */ 1207 /* Prepare transfer mode register value. (2.2.5) */
1199 mode = SDHC_BLOCK_COUNT_ENABLE; 1208 mode = SDHC_BLOCK_COUNT_ENABLE;
1200 if (ISSET(cmd->c_flags, SCF_CMD_READ)) 1209 if (ISSET(cmd->c_flags, SCF_CMD_READ))
1201 mode |= SDHC_READ_MODE; 1210 mode |= SDHC_READ_MODE;
1202 if (blkcount > 1) { 1211 if (blkcount > 1) {
1203 mode |= SDHC_MULTI_BLOCK_MODE; 1212 mode |= SDHC_MULTI_BLOCK_MODE;
1204 /* XXX only for memory commands? */ 1213 /* XXX only for memory commands? */
1205 mode |= SDHC_AUTO_CMD12_ENABLE; 1214 mode |= SDHC_AUTO_CMD12_ENABLE;
1206 } 1215 }
1207 if (cmd->c_dmamap != NULL && cmd->c_datalen > 0 && 1216 if (cmd->c_dmamap != NULL && cmd->c_datalen > 0 &&
1208 !ISSET(sc->sc_flags, SDHC_FLAG_EXTERNAL_DMA)) { 1217 ISSET(hp->flags, SHF_MODE_DMAEN)) {
1209 mode |= SDHC_DMA_ENABLE; 1218 mode |= SDHC_DMA_ENABLE;
1210 } 1219 }
1211 1220
1212 /* 1221 /*
1213 * Prepare command register value. (2.2.6) 1222 * Prepare command register value. (2.2.6)
1214 */ 1223 */
1215 command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) << SDHC_COMMAND_INDEX_SHIFT; 1224 command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) << SDHC_COMMAND_INDEX_SHIFT;
1216 1225
1217 if (ISSET(cmd->c_flags, SCF_RSP_CRC)) 1226 if (ISSET(cmd->c_flags, SCF_RSP_CRC))
1218 command |= SDHC_CRC_CHECK_ENABLE; 1227 command |= SDHC_CRC_CHECK_ENABLE;
1219 if (ISSET(cmd->c_flags, SCF_RSP_IDX)) 1228 if (ISSET(cmd->c_flags, SCF_RSP_IDX))
1220 command |= SDHC_INDEX_CHECK_ENABLE; 1229 command |= SDHC_INDEX_CHECK_ENABLE;
1221 if (cmd->c_data != NULL) 1230 if (cmd->c_data != NULL)
@@ -1241,27 +1250,28 @@ sdhc_start_command(struct sdhc_host *hp, @@ -1241,27 +1250,28 @@ sdhc_start_command(struct sdhc_host *hp,
1241 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { 1250 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
1242 blksize |= (MAX(0, PAGE_SHIFT - 12) & SDHC_DMA_BOUNDARY_MASK) << 1251 blksize |= (MAX(0, PAGE_SHIFT - 12) & SDHC_DMA_BOUNDARY_MASK) <<
1243 SDHC_DMA_BOUNDARY_SHIFT; /* PAGE_SIZE DMA boundary */ 1252 SDHC_DMA_BOUNDARY_SHIFT; /* PAGE_SIZE DMA boundary */
1244 } 1253 }
1245 1254
1246 mutex_enter(&hp->host_mtx); 1255 mutex_enter(&hp->host_mtx);
1247 1256
1248 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { 1257 if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
1249 /* Alert the user not to remove the card. */ 1258 /* Alert the user not to remove the card. */
1250 HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON); 1259 HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
1251 } 1260 }
1252 1261
1253 /* Set DMA start address. */ 1262 /* Set DMA start address. */
1254 if (ISSET(mode, SDHC_DMA_ENABLE)) 1263 if (ISSET(mode, SDHC_DMA_ENABLE) &&
 1264 !ISSET(sc->sc_flags, SDHC_FLAG_EXTERNAL_DMA))
1255 HWRITE4(hp, SDHC_DMA_ADDR, cmd->c_dmamap->dm_segs[0].ds_addr); 1265 HWRITE4(hp, SDHC_DMA_ADDR, cmd->c_dmamap->dm_segs[0].ds_addr);
1256 1266
1257 /* 1267 /*
1258 * Start a CPU data transfer. Writing to the high order byte 1268 * Start a CPU data transfer. Writing to the high order byte
1259 * of the SDHC_COMMAND register triggers the SD command. (1.5) 1269 * of the SDHC_COMMAND register triggers the SD command. (1.5)
1260 */ 1270 */
1261 if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) { 1271 if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
1262 HWRITE4(hp, SDHC_BLOCK_SIZE, blksize | (blkcount << 16)); 1272 HWRITE4(hp, SDHC_BLOCK_SIZE, blksize | (blkcount << 16));
1263 HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg); 1273 HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg);
1264 HWRITE4(hp, SDHC_TRANSFER_MODE, mode | (command << 16)); 1274 HWRITE4(hp, SDHC_TRANSFER_MODE, mode | (command << 16));
1265 } else { 1275 } else {
1266 HWRITE2(hp, SDHC_BLOCK_SIZE, blksize); 1276 HWRITE2(hp, SDHC_BLOCK_SIZE, blksize);
1267 HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount); 1277 HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount);

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

--- src/sys/dev/sdmmc/sdhcvar.h 2014/10/04 18:09:32 1.15
+++ src/sys/dev/sdmmc/sdhcvar.h 2015/04/14 18:34:29 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sdhcvar.h,v 1.15 2014/10/04 18:09:32 jmcneill Exp $ */ 1/* $NetBSD: sdhcvar.h,v 1.16 2015/04/14 18:34:29 bouyer 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
@@ -26,41 +26,42 @@ @@ -26,41 +26,42 @@
26 26
27struct sdhc_host; 27struct sdhc_host;
28struct sdmmc_command; 28struct sdmmc_command;
29 29
30struct sdhc_softc { 30struct sdhc_softc {
31 device_t sc_dev; 31 device_t sc_dev;
32 32
33 struct sdhc_host **sc_host; 33 struct sdhc_host **sc_host;
34 int sc_nhosts; 34 int sc_nhosts;
35 35
36 bus_dma_tag_t sc_dmat; 36 bus_dma_tag_t sc_dmat;
37 37
38 uint32_t sc_flags; 38 uint32_t sc_flags;
39#define SDHC_FLAG_USE_DMA 0x0001 39#define SDHC_FLAG_USE_DMA 0x00000001
40#define SDHC_FLAG_FORCE_DMA 0x0002 40#define SDHC_FLAG_FORCE_DMA 0x00000002
41#define SDHC_FLAG_NO_PWR0 0x0004 /* Freescale ESDHC */ 41#define SDHC_FLAG_NO_PWR0 0x00000004 /* Freescale ESDHC */
42#define SDHC_FLAG_HAVE_DVS 0x0008 /* Freescale ESDHC */ 42#define SDHC_FLAG_HAVE_DVS 0x00000008 /* Freescale ESDHC */
43#define SDHC_FLAG_32BIT_ACCESS 0x0010 /* Freescale ESDHC */ 43#define SDHC_FLAG_32BIT_ACCESS 0x00000010 /* Freescale ESDHC */
44#define SDHC_FLAG_ENHANCED 0x0020 /* Freescale ESDHC */ 44#define SDHC_FLAG_ENHANCED 0x00000020 /* Freescale ESDHC */
45#define SDHC_FLAG_8BIT_MODE 0x0040 /* MMC 8bit mode is supported */ 45#define SDHC_FLAG_8BIT_MODE 0x00000040 /* MMC 8bit mode is supported */
46#define SDHC_FLAG_HAVE_CGM 0x0080 /* Netlogic XLP */ 46#define SDHC_FLAG_HAVE_CGM 0x00000080 /* Netlogic XLP */
47#define SDHC_FLAG_NO_LED_ON 0x0100 /* 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 0x0200 /* No device provided capabilities */ 48#define SDHC_FLAG_HOSTCAPS 0x00000200 /* No device provided capabilities */
49#define SDHC_FLAG_RSP136_CRC 0x0400 /* 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 0x0800 /* Single transfer only */ 50#define SDHC_FLAG_SINGLE_ONLY 0x00000800 /* Single transfer only */
51#define SDHC_FLAG_WAIT_RESET 0x1000 /* 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 0x2000 /* 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 0x4000 53#define SDHC_FLAG_EXTERNAL_DMA 0x00004000
 54#define SDHC_FLAG_EXTDMA_DMAEN 0x00008000 /* ext. dma need SDHC_DMA_ENABLE */
54 55
55 uint32_t sc_clkbase; 56 uint32_t sc_clkbase;
56 int sc_clkmsk; /* Mask for SDCLK */ 57 int sc_clkmsk; /* Mask for SDCLK */
57 uint32_t sc_caps;/* attachment provided capabilities */ 58 uint32_t sc_caps;/* attachment provided capabilities */
58 59
59 int (*sc_vendor_rod)(struct sdhc_softc *, int); 60 int (*sc_vendor_rod)(struct sdhc_softc *, int);
60 int (*sc_vendor_write_protect)(struct sdhc_softc *); 61 int (*sc_vendor_write_protect)(struct sdhc_softc *);
61 int (*sc_vendor_card_detect)(struct sdhc_softc *); 62 int (*sc_vendor_card_detect)(struct sdhc_softc *);
62 int (*sc_vendor_bus_clock)(struct sdhc_softc *, int); 63 int (*sc_vendor_bus_clock)(struct sdhc_softc *, int);
63 int (*sc_vendor_transfer_data_dma)(struct sdhc_softc *, struct sdmmc_command *); 64 int (*sc_vendor_transfer_data_dma)(struct sdhc_softc *, struct sdmmc_command *);
64}; 65};
65 66
66/* Host controller functions called by the attachment driver. */ 67/* Host controller functions called by the attachment driver. */