Add sdmmc_io_set_blocklen() which allows to set the block length of an
authorpatrick <patrick@openbsd.org>
Sun, 11 Feb 2018 20:58:40 +0000 (20:58 +0000)
committerpatrick <patrick@openbsd.org>
Sun, 11 Feb 2018 20:58:40 +0000 (20:58 +0000)
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@

sys/dev/sdmmc/sdmmc.c
sys/dev/sdmmc/sdmmc_io.c
sys/dev/sdmmc/sdmmc_ioreg.h
sys/dev/sdmmc/sdmmcvar.h

index 863f4ee..bb7d4cc 100644 (file)
@@ -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;
 }
 
index 206d578..4d2550f 100644 (file)
@@ -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;
+}
index b23edd8..1fdea47 100644 (file)
@@ -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
index 0b2ffce..0510bda 100644 (file)
@@ -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 *);