summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2018-02-11 20:58:41 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2018-02-11 20:58:41 +0000
commit301da83b54958dbdfb8e5d06650e8e6c2364c26e (patch)
tree4ad5c01a0b77872998ab979b3b119ffb406ca541 /sys/dev
parentff613e27743dec56a87f53dbed8c980e0432b6e6 (diff)
Add sdmmc_io_set_blocklen() which allows to set the block length of an
SDIO function. This is necessary for some SDIO cards that need to be talked with using smaller block lengths than the maximum supported by the host controller. ok kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sdmmc/sdmmc.c3
-rw-r--r--sys/dev/sdmmc/sdmmc_io.c27
-rw-r--r--sys/dev/sdmmc/sdmmc_ioreg.h6
-rw-r--r--sys/dev/sdmmc/sdmmcvar.h4
4 files changed, 33 insertions, 7 deletions
diff --git a/sys/dev/sdmmc/sdmmc.c b/sys/dev/sdmmc/sdmmc.c
index 863f4ee69f4..bb7d4cc96b6 100644
--- a/sys/dev/sdmmc/sdmmc.c
+++ b/sys/dev/sdmmc/sdmmc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc.c,v 1.48 2017/12/24 12:55:52 kettenis Exp $ */
+/* $OpenBSD: sdmmc.c,v 1.49 2018/02/11 20:58:40 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -503,6 +503,7 @@ sdmmc_function_alloc(struct sdmmc_softc *sc)
sf->cis.manufacturer = SDMMC_VENDOR_INVALID;
sf->cis.product = SDMMC_PRODUCT_INVALID;
sf->cis.function = SDMMC_FUNCTION_INVALID;
+ sf->cur_blklen = sdmmc_chip_host_maxblklen(sc->sct, sc->sch);
return sf;
}
diff --git a/sys/dev/sdmmc/sdmmc_io.c b/sys/dev/sdmmc/sdmmc_io.c
index 206d578f06e..4d2550f0bca 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.31 2018/02/11 20:57:57 patrick Exp $ */
+/* $OpenBSD: sdmmc_io.c,v 1.32 2018/02/11 20:58:40 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -46,6 +46,7 @@ int sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
int, u_char *);
void sdmmc_io_reset(struct sdmmc_softc *);
int sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
+void sdmmc_io_set_blocklen(struct sdmmc_function *, unsigned int);
#ifdef SDMMC_DEBUG
#define DPRINTF(s) printf s
@@ -415,7 +416,7 @@ sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
cmd.c_data = datap;
cmd.c_datalen = datalen;
- cmd.c_blklen = MIN(datalen, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
+ cmd.c_blklen = MIN(datalen, sf->cur_blklen);
if (!ISSET(arg, SD_ARG_CMD53_WRITE))
cmd.c_flags |= SCF_CMD_READ;
@@ -767,3 +768,25 @@ sdmmc_intr_task(void *arg)
sdmmc_chip_card_intr_ack(sc->sct, sc->sch);
splx(s);
}
+
+void
+sdmmc_io_set_blocklen(struct sdmmc_function *sf, unsigned int blklen)
+{
+ struct sdmmc_softc *sc = sf->sc;
+ struct sdmmc_function *sf0 = sc->sc_fn0;
+
+ rw_assert_wrlock(&sc->sc_lock);
+
+ if (blklen > sdmmc_chip_host_maxblklen(sc->sct, sc->sch))
+ return;
+
+ if (blklen == 0) {
+ blklen = min(512, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
+ }
+
+ sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
+ SD_IO_FBR_BLOCKLEN, blklen & 0xff);
+ sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
+ SD_IO_FBR_BLOCKLEN+ 1, (blklen >> 8) & 0xff);
+ sf->cur_blklen = blklen;
+}
diff --git a/sys/dev/sdmmc/sdmmc_ioreg.h b/sys/dev/sdmmc/sdmmc_ioreg.h
index b23edd898d7..1fdea4792b7 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.6 2016/04/23 14:15:59 kettenis Exp $ */
+/* $OpenBSD: sdmmc_ioreg.h,v 1.7 2018/02/11 20:58:40 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -75,8 +75,8 @@
#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
/* Function Basic Registers (FBR) */
-#define SD_IO_FBR_START 0x00100
-#define SD_IO_FBR_SIZE 0x00700
+#define SD_IO_FBR_BASE(f) ((f) * 0x100)
+#define SD_IO_FBR_BLOCKLEN 0x10
/* Card Information Structure (CIS) */
#define SD_IO_CIS_START 0x01000
diff --git a/sys/dev/sdmmc/sdmmcvar.h b/sys/dev/sdmmc/sdmmcvar.h
index 0b2ffce42be..0510bdaa6d1 100644
--- a/sys/dev/sdmmc/sdmmcvar.h
+++ b/sys/dev/sdmmc/sdmmcvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmcvar.h,v 1.27 2018/02/11 20:57:57 patrick Exp $ */
+/* $OpenBSD: sdmmcvar.h,v 1.28 2018/02/11 20:58:40 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -151,6 +151,7 @@ struct sdmmc_function {
int number; /* I/O function number or -1 */
struct device *child; /* function driver */
struct sdmmc_cis cis; /* decoded CIS */
+ unsigned int cur_blklen; /* current block length */
/* SD/MMC memory card members */
struct sdmmc_csd csd; /* decoded CSD value */
struct sdmmc_cid cid; /* decoded CID value */
@@ -267,6 +268,7 @@ int sdmmc_io_write_region_1(struct sdmmc_function *, int, u_char *, int);
int sdmmc_io_function_ready(struct sdmmc_function *);
int sdmmc_io_function_enable(struct sdmmc_function *);
void sdmmc_io_function_disable(struct sdmmc_function *);
+void sdmmc_io_set_blocklen(struct sdmmc_function *, unsigned int);
int sdmmc_read_cis(struct sdmmc_function *, struct sdmmc_cis *);
void sdmmc_print_cis(struct sdmmc_function *);