summaryrefslogtreecommitdiffstats
path: root/sys/dev/sdmmc
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2018-05-25 00:12:53 +0000
committerpatrick <patrick@openbsd.org>2018-05-25 00:12:53 +0000
commit5e0782b17abc2070c235843e37de911ce3f98ef8 (patch)
treeb6dd000cd5eecfa79f97b25ae9e5b8458ed12538 /sys/dev/sdmmc
parentFor SDIO multi-blocks we must not use the AUTO CMD12 feature, (diff)
downloadwireguard-openbsd-5e0782b17abc2070c235843e37de911ce3f98ef8.tar.xz
wireguard-openbsd-5e0782b17abc2070c235843e37de911ce3f98ef8.zip
So far the SDIO stack issued one transfer for every 64 byte to be
copied. This severely limits the speed over the bus. By using block mode we can issue block-sized transfers, which bumps the transfer size to at least 512 bytes. By using multi-block mode we can copy up to 511 blocks per transfer. ok kettenis@
Diffstat (limited to 'sys/dev/sdmmc')
-rw-r--r--sys/dev/sdmmc/sdmmc_io.c102
-rw-r--r--sys/dev/sdmmc/sdmmc_ioreg.h4
2 files changed, 66 insertions, 40 deletions
diff --git a/sys/dev/sdmmc/sdmmc_io.c b/sys/dev/sdmmc/sdmmc_io.c
index 87259711a69..37f3f67d7e5 100644
--- a/sys/dev/sdmmc/sdmmc_io.c
+++ b/sys/dev/sdmmc/sdmmc_io.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc_io.c,v 1.33 2018/05/21 17:12:16 kettenis Exp $ */
+/* $OpenBSD: sdmmc_io.c,v 1.34 2018/05/25 00:12:53 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -383,11 +383,12 @@ sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf,
* Useful values of `arg' to pass in are either SD_ARG_CMD53_READ or
* SD_ARG_CMD53_WRITE. SD_ARG_CMD53_INCREMENT may be ORed into `arg'
* to access successive register locations instead of accessing the
- * same register many times.
+ * same register many times. SD_ARG_CMD53_BLOCK_MODE may be ORed
+ * into `arg' to indicate that the length is a number of blocks.
*/
int
sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
- int reg, u_char *datap, int datalen, int arg)
+ int reg, u_char *datap, int len, int arg)
{
struct sdmmc_command cmd;
int error;
@@ -406,7 +407,7 @@ sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
SD_ARG_CMD53_FUNC_SHIFT;
arg |= (reg & SD_ARG_CMD53_REG_MASK) <<
SD_ARG_CMD53_REG_SHIFT;
- arg |= (datalen & SD_ARG_CMD53_LENGTH_MASK) <<
+ arg |= (len & SD_ARG_CMD53_LENGTH_MASK) <<
SD_ARG_CMD53_LENGTH_SHIFT;
bzero(&cmd, sizeof cmd);
@@ -414,8 +415,13 @@ sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
cmd.c_arg = arg;
cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
cmd.c_data = datap;
- cmd.c_datalen = datalen;
- cmd.c_blklen = MIN(datalen, sf->cur_blklen);
+ if (ISSET(arg, SD_ARG_CMD53_BLOCK_MODE)) {
+ cmd.c_datalen = len * sf->cur_blklen;
+ cmd.c_blklen = sf->cur_blklen;
+ } else {
+ cmd.c_datalen = len;
+ cmd.c_blklen = MIN(len, sf->cur_blklen);
+ }
if (!ISSET(arg, SD_ARG_CMD53_WRITE))
cmd.c_flags |= SCF_CMD_READ;
@@ -492,88 +498,108 @@ int
sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
int datalen)
{
- int error;
+ int blocks, error = 0;
rw_assert_wrlock(&sf->sc->sc_lock);
- while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
+ while (datalen >= sf->cur_blklen) {
+ blocks = MIN(datalen / sf->cur_blklen,
+ SD_ARG_CMD53_LENGTH_MAX);
error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
- SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ);
+ blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_BLOCK_MODE);
if (error)
return error;
- data += SD_ARG_CMD53_LENGTH_MAX;
- datalen -= SD_ARG_CMD53_LENGTH_MAX;
+ data += blocks * sf->cur_blklen;
+ datalen -= blocks * sf->cur_blklen;
}
- return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
- SD_ARG_CMD53_READ);
+ if (datalen)
+ error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
+ SD_ARG_CMD53_READ);
+
+ return error;
}
int
sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
int datalen)
{
- int error;
+ int blocks, error = 0;
rw_assert_wrlock(&sf->sc->sc_lock);
- while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
+ while (datalen >= sf->cur_blklen) {
+ blocks = MIN(datalen / sf->cur_blklen,
+ SD_ARG_CMD53_LENGTH_MAX);
error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
- SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE);
+ blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_BLOCK_MODE);
if (error)
return error;
- data += SD_ARG_CMD53_LENGTH_MAX;
- datalen -= SD_ARG_CMD53_LENGTH_MAX;
+ data += blocks * sf->cur_blklen;
+ datalen -= blocks * sf->cur_blklen;
}
- return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
- SD_ARG_CMD53_WRITE);
+ if (datalen)
+ error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
+ SD_ARG_CMD53_WRITE);
+
+ return error;
}
int
sdmmc_io_read_region_1(struct sdmmc_function *sf, int reg, u_char *data,
int datalen)
{
- int error;
+ int blocks, error = 0;
rw_assert_wrlock(&sf->sc->sc_lock);
- while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
+ while (datalen >= sf->cur_blklen) {
+ blocks = MIN(datalen / sf->cur_blklen,
+ SD_ARG_CMD53_LENGTH_MAX);
error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
- SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ |
- SD_ARG_CMD53_INCREMENT);
+ blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT |
+ SD_ARG_CMD53_BLOCK_MODE);
if (error)
return error;
- reg += SD_ARG_CMD53_LENGTH_MAX;
- data += SD_ARG_CMD53_LENGTH_MAX;
- datalen -= SD_ARG_CMD53_LENGTH_MAX;
+ reg += blocks * sf->cur_blklen;
+ data += blocks * sf->cur_blklen;
+ datalen -= blocks * sf->cur_blklen;
}
- return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
- SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
+ if (datalen)
+ error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
+ SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
+
+ return error;
}
int
sdmmc_io_write_region_1(struct sdmmc_function *sf, int reg, u_char *data,
int datalen)
{
- int error;
+ int blocks, error = 0;
rw_assert_wrlock(&sf->sc->sc_lock);
- while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
+ while (datalen >= sf->cur_blklen) {
+ blocks = MIN(datalen / sf->cur_blklen,
+ SD_ARG_CMD53_LENGTH_MAX);
error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
- SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE |
- SD_ARG_CMD53_INCREMENT);
+ blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT |
+ SD_ARG_CMD53_BLOCK_MODE);
if (error)
return error;
- reg += SD_ARG_CMD53_LENGTH_MAX;
- data += SD_ARG_CMD53_LENGTH_MAX;
- datalen -= SD_ARG_CMD53_LENGTH_MAX;
+ reg += blocks * sf->cur_blklen;
+ data += blocks * sf->cur_blklen;
+ datalen -= blocks * sf->cur_blklen;
}
- return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
- SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
+ if (datalen)
+ error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
+ SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
+
+ return error;
}
int
diff --git a/sys/dev/sdmmc/sdmmc_ioreg.h b/sys/dev/sdmmc/sdmmc_ioreg.h
index 1fdea4792b7..fee72e55446 100644
--- a/sys/dev/sdmmc/sdmmc_ioreg.h
+++ b/sys/dev/sdmmc/sdmmc_ioreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc_ioreg.h,v 1.7 2018/02/11 20:58:40 patrick Exp $ */
+/* $OpenBSD: sdmmc_ioreg.h,v 1.8 2018/05/25 00:12:53 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -47,7 +47,7 @@
#define SD_ARG_CMD53_REG_MASK 0x1ffff
#define SD_ARG_CMD53_LENGTH_SHIFT 0
#define SD_ARG_CMD53_LENGTH_MASK 0x1ff
-#define SD_ARG_CMD53_LENGTH_MAX 64 /* XXX should be 511? */
+#define SD_ARG_CMD53_LENGTH_MAX 511
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R4(resp) ((resp)[0])