Module Name: src Committed By: mlelstv Date: Sun Sep 1 05:45:42 UTC 2019
Modified Files: src/sys/dev/sdmmc: sdmmc.c sdmmc_cis.c sdmmc_io.c sdmmc_ioreg.h sdmmcvar.h Log Message: >From OpenBSD: - support block length per function - add functions to read/write regions Decode (but not use) SDIO tuple in CIS. Fix locking. Add more SDIO defines (partially from version 3.0). To generate a diff of this commit: cvs rdiff -u -r1.36 -r1.37 src/sys/dev/sdmmc/sdmmc.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/sdmmc/sdmmc_cis.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/sdmmc/sdmmc_io.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/sdmmc/sdmmc_ioreg.h cvs rdiff -u -r1.30 -r1.31 src/sys/dev/sdmmc/sdmmcvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/sdmmc/sdmmc.c diff -u src/sys/dev/sdmmc/sdmmc.c:1.36 src/sys/dev/sdmmc/sdmmc.c:1.37 --- src/sys/dev/sdmmc/sdmmc.c:1.36 Tue Nov 6 16:01:38 2018 +++ src/sys/dev/sdmmc/sdmmc.c Sun Sep 1 05:45:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmc.c,v 1.36 2018/11/06 16:01:38 jmcneill Exp $ */ +/* $NetBSD: sdmmc.c,v 1.37 2019/09/01 05:45:42 mlelstv Exp $ */ /* $OpenBSD: sdmmc.c,v 1.18 2009/01/09 10:58:38 jsg Exp $ */ /* @@ -49,7 +49,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.36 2018/11/06 16:01:38 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.37 2019/09/01 05:45:42 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -656,6 +656,7 @@ sdmmc_function_alloc(struct sdmmc_softc sf->cis.product = SDMMC_PRODUCT_INVALID; sf->cis.function = SDMMC_FUNCTION_INVALID; sf->width = 1; + sf->blklen = sdmmc_chip_host_maxblklen(sc->sc_sct, sc->sc_sch); if (ISSET(sc->sc_flags, SMF_MEM_MODE) && ISSET(sc->sc_caps, SMC_CAPS_DMA) && Index: src/sys/dev/sdmmc/sdmmc_cis.c diff -u src/sys/dev/sdmmc/sdmmc_cis.c:1.5 src/sys/dev/sdmmc/sdmmc_cis.c:1.6 --- src/sys/dev/sdmmc/sdmmc_cis.c:1.5 Sun Jan 28 14:34:06 2018 +++ src/sys/dev/sdmmc/sdmmc_cis.c Sun Sep 1 05:45:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmc_cis.c,v 1.5 2018/01/28 14:34:06 jmcneill Exp $ */ +/* $NetBSD: sdmmc_cis.c,v 1.6 2019/09/01 05:45:42 mlelstv Exp $ */ /* $OpenBSD: sdmmc_cis.c,v 1.1 2006/06/01 21:53:41 uwe Exp $ */ /* @@ -20,7 +20,7 @@ /* Routines to decode the Card Information Structure of SD I/O cards */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdmmc_cis.c,v 1.5 2018/01/28 14:34:06 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdmmc_cis.c,v 1.6 2019/09/01 05:45:42 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -130,6 +130,7 @@ decode_funce_function(struct sdmmc_funct max_blk_size = sdmmc_io_read_1(sf0, reg + 11); max_blk_size |= sdmmc_io_read_1(sf0, reg + 12) << 8; +device_printf(dev, "MAX_BLK_SIZE%d = %d\n", sf->number, max_blk_size); DPRINTF(("CISTPL_FUNCE: MAX_BLK_SIZE=0x%x\n", max_blk_size)); } @@ -259,6 +260,11 @@ sdmmc_read_cis(struct sdmmc_function *sf reg += tpllen; break; + case PCMCIA_CISTPL_SDIO: + aprint_normal_dev(dev, "SDIO function\n"); + reg += tpllen; + break; + default: /* * Tuple codes between 80h-8Fh are vendor unique. Index: src/sys/dev/sdmmc/sdmmc_io.c diff -u src/sys/dev/sdmmc/sdmmc_io.c:1.14 src/sys/dev/sdmmc/sdmmc_io.c:1.15 --- src/sys/dev/sdmmc/sdmmc_io.c:1.14 Sun Oct 14 17:37:40 2018 +++ src/sys/dev/sdmmc/sdmmc_io.c Sun Sep 1 05:45:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmc_io.c,v 1.14 2018/10/14 17:37:40 jdolecek Exp $ */ +/* $NetBSD: sdmmc_io.c,v 1.15 2019/09/01 05:45:42 mlelstv Exp $ */ /* $OpenBSD: sdmmc_io.c,v 1.10 2007/09/17 01:33:33 krw Exp $ */ /* @@ -20,7 +20,7 @@ /* Routines for SD I/O cards. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.14 2018/10/14 17:37:40 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.15 2019/09/01 05:45:42 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -194,6 +194,8 @@ sdmmc_io_init(struct sdmmc_softc *sc, st SDMMC_LOCK(sc); + sf->blklen = sdmmc_chip_host_maxblklen(sc->sc_sct, sc->sc_sch); + if (sf->number == 0) { reg = sdmmc_io_read_1(sf, SD_IO_CCCR_CAPABILITY); if (!(reg & CCCR_CAPS_LSC) || (reg & CCCR_CAPS_4BLS)) { @@ -395,8 +397,8 @@ sdmmc_io_rw_extended(struct sdmmc_softc 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->sc_sct,sc->sc_sch)); + cmd.c_blklen = MIN(datalen, sf->blklen); + if (!ISSET(arg, SD_ARG_CMD53_WRITE)) cmd.c_flags |= SCF_CMD_READ; @@ -476,21 +478,26 @@ int sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data, int datalen) { - int error; + int blocks, bytes, error = 0; /* Don't lock */ - while (datalen > SD_ARG_CMD53_LENGTH_MAX) { + while (datalen >= sf->blklen) { + //blocks = imin(datalen / sf->blklen, + // SD_ARG_CMD53_LENGTH_MAX); + blocks = 1; + bytes = blocks * sf->blklen; error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, - SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ); + bytes, SD_ARG_CMD53_READ); if (error) goto error; - data += SD_ARG_CMD53_LENGTH_MAX; - datalen -= SD_ARG_CMD53_LENGTH_MAX; + data += bytes; + datalen -= bytes; } - error = 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); error: return error; } @@ -499,21 +506,85 @@ int sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data, int datalen) { - int error; + int blocks, bytes, error = 0; + + /* Don't lock */ + + while (datalen >= sf->blklen) { + //blocks = imin(datalen / sf->blklen, + // SD_ARG_CMD53_LENGTH_MAX); + blocks = 1; + bytes = blocks * sf->blklen; + error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, + bytes, SD_ARG_CMD53_WRITE); + if (error) + goto error; + data += bytes; + datalen -= bytes; + } + + if (datalen) + error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen, + SD_ARG_CMD53_WRITE); +error: + return error; +} + + +int +sdmmc_io_read_region_1(struct sdmmc_function *sf, int reg, u_char *data, + int datalen) +{ + int blocks, bytes, error = 0; + + /* Don't lock */ + + while (datalen >= sf->blklen) { + //blocks = imin(datalen / sf->blklen, + // SD_ARG_CMD53_LENGTH_MAX); + blocks = 1; + bytes = blocks * sf->blklen; + error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, + bytes, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT); + if (error) + goto error; + reg += bytes; + data += bytes; + datalen -= bytes; + } + + if (datalen) + error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen, + SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT); +error: + return error; +} + +int +sdmmc_io_write_region_1(struct sdmmc_function *sf, int reg, u_char *data, + int datalen) +{ + int blocks, bytes, error = 0; /* Don't lock */ - while (datalen > SD_ARG_CMD53_LENGTH_MAX) { + while (datalen >= sf->blklen) { + //blocks = imin(datalen / sf->blklen, + // SD_ARG_CMD53_LENGTH_MAX); + blocks = 1; + bytes = blocks * sf->blklen; error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, - SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE); + bytes, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT); if (error) goto error; - data += SD_ARG_CMD53_LENGTH_MAX; - datalen -= SD_ARG_CMD53_LENGTH_MAX; + reg += bytes; + data += bytes; + datalen -= bytes; } - error = 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 | SD_ARG_CMD53_INCREMENT); error: return error; } @@ -539,7 +610,8 @@ sdmmc_io_reset(struct sdmmc_softc *sc) { u_char data = CCCR_CTL_RES; - if (sdmmc_io_rw_direct(sc, NULL, SD_IO_CCCR_CTL, &data, SD_ARG_CMD52_WRITE) == 0) + if (sdmmc_io_rw_direct(sc, NULL, SD_IO_CCCR_CTL, &data, + SD_ARG_CMD52_WRITE) == 0) sdmmc_delay(100000); } @@ -597,11 +669,9 @@ sdmmc_intr_enable(struct sdmmc_function uint8_t reg; SDMMC_LOCK(sc); - mutex_enter(&sc->sc_intr_task_mtx); reg = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_INTEN); reg |= 1 << sf->number; sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_INTEN, reg); - mutex_exit(&sc->sc_intr_task_mtx); SDMMC_UNLOCK(sc); } @@ -613,11 +683,9 @@ sdmmc_intr_disable(struct sdmmc_function uint8_t reg; SDMMC_LOCK(sc); - mutex_enter(&sc->sc_intr_task_mtx); reg = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_INTEN); reg &= ~(1 << sf->number); sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_INTEN, reg); - mutex_exit(&sc->sc_intr_task_mtx); SDMMC_UNLOCK(sc); } @@ -719,3 +787,30 @@ sdmmc_intr_task(void *arg) sdmmc_chip_card_intr_ack(sc->sc_sct, sc->sc_sch); } + +int +sdmmc_io_set_blocklen(struct sdmmc_softc *sc, struct sdmmc_function *sf, + int blklen) +{ + struct sdmmc_function *sf0 = sc->sc_fn0; + int error = EINVAL; + + SDMMC_LOCK(sc); + + if (blklen <= 0 || + blklen > sdmmc_chip_host_maxblklen(sc->sc_sct, sc->sc_sch)) + goto err; + + sdmmc_io_write_1(sf0, SD_IO_FBR(sf->number) + + SD_IO_FBR_BLOCKLEN, blklen & 0xff); + sdmmc_io_write_1(sf0, SD_IO_FBR(sf->number) + + SD_IO_FBR_BLOCKLEN + 1, (blklen >> 8) & 0xff); + + sf->blklen = blklen; + error = 0; + +err: + SDMMC_UNLOCK(sc); + + return error; +} Index: src/sys/dev/sdmmc/sdmmc_ioreg.h diff -u src/sys/dev/sdmmc/sdmmc_ioreg.h:1.3 src/sys/dev/sdmmc/sdmmc_ioreg.h:1.4 --- src/sys/dev/sdmmc/sdmmc_ioreg.h:1.3 Wed Jul 24 05:45:42 2019 +++ src/sys/dev/sdmmc/sdmmc_ioreg.h Sun Sep 1 05:45:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmc_ioreg.h,v 1.3 2019/07/24 05:45:42 msaitoh Exp $ */ +/* $NetBSD: sdmmc_ioreg.h,v 1.4 2019/09/01 05:45:42 mlelstv Exp $ */ /* $OpenBSD: sdmmc_ioreg.h,v 1.4 2007/06/02 01:48:37 uwe Exp $ */ /* @@ -48,7 +48,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 64 /* 48-bit response decoding (32 bits w/o CRC) */ #define MMC_R4(resp) ((resp)[0]) @@ -68,16 +68,19 @@ #define CCCR_CCCR_REV_1_00 0 #define CCCR_CCCR_REV_1_10 1 #define CCCR_CCCR_REV_1_20 2 +#define CCCR_CCCR_REV_3_00 3 #define SD_IO_CCCR_SDIO_REV(r) (((r) >> 4) & 0xf) #define CCCR_SDIO_REV_1_00 0 #define CCCR_SDIO_REV_1_10 1 #define CCCR_SDIO_REV_1_20 2 /* (unreleased) */ #define CCCR_SDIO_REV_2_00 3 +#define CCCR_SDIO_REV_3_00 4 #define SD_IO_CCCR_SPEC_REV 0x01 #define SD_IO_CCCR_SD_PHYS_SPEC_VER(r) ((r) & 0xf) #define CCCR_SD_PHYS_SPEC_VER_1_01 0 #define CCCR_SD_PHYS_SPEC_VER_1_10 1 #define CCCR_SD_PHYS_SPEC_VER_2_00 2 +#define CCCR_SD_PHYS_SPEC_VER_3_00 3 #define SD_IO_CCCR_FN_ENABLE 0x02 #define SD_IO_CCCR_FN_IOREADY 0x03 #define SD_IO_CCCR_FN_INTEN 0x04 @@ -88,6 +91,9 @@ #define SD_IO_CCCR_BUS_WIDTH 0x07 #define CCCR_BUS_WIDTH_4 (2<<0) #define CCCR_BUS_WIDTH_1 (0<<0) +#define CCCR_BUS_ECSI (1<<5) +#define CCCR_BUS_SCSI (1<<6) +#define CCCR_BUS_NOCD (1<<7) #define SD_IO_CCCR_CAPABILITY 0x08 #define CCCR_CAPS_SDC (1<<0) #define CCCR_CAPS_SMB (1<<1) /* Multi-Block support */ @@ -100,6 +106,8 @@ #define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */ #define SD_IO_CCCR_BUS_SUSPEND 0x0c #define SD_IO_CCCR_FUNC_SELECT 0x0d +#define SD_IO_CCCR_EXEC_FLAGS 0x0e +#define SD_IO_CCCR_READY_FLAGS 0x0f #define CCCR_FUNC_FS(r) ((r) & 0xf) #define CCCR_FUNC_FS_FN(fn) ((fn) & 0x7) #define CCCR_FUNC_FS_MEM 8 @@ -110,12 +118,36 @@ #define SD_IO_CCCR_HIGH_SPEED 0x13 #define CCCR_HIGH_SPEED_SHS (1<<0) /* Support High-Speed */ #define CCCR_HIGH_SPEED_EHS (1<<1) /* Enable High-Speed */ +#define CCCR_HIGH_SPEED_SDR50 (2<<1) +#define CCCR_HIGH_SPEED_SDR104 (3<<1) +#define CCCR_HIGH_SPEED_DDR50 (4<<1) +#define SD_IO_CCCR_UHS 0x14 +#define CCCR_UHS_SDR50 (1<<0) +#define CCCR_UHS_SDR104 (1<<1) +#define CCCR_UHS_DDR50 (1<<2) +#define SD_IO_DRIVE_STRENGTH 0x15 +#define CCCR_DRIVE_SDTA (1<<0) +#define CCCR_DRIVE_SDTC (1<<1) +#define CCCR_DRIVE_SDTD (1<<2) /* Function Basic Registers (FBR) */ #define SD_IO_FBR_START 0x00100 #define SD_IO_FBR_SIZE 0x100 #define SD_IO_FBR(func) ((((func) - 1) * SD_IO_FBR_SIZE) + SD_IO_FBR_START) + +/* FBR offsets */ +#define SD_IO_FBR_BASIC 0x00 #define FBR_STD_FUNC_IF_CODE(v) ((v) & 0x0f) +#define FBR_STD_FUNC_CSA(v) ((v) & 0x40) /* supports CSA */ +#define FBR_STD_FUNC_CSAE(v) ((v) & 0x80) /* enable CSA */ +#define SD_IO_FBR_EXT 0x01 +#define SD_IO_FBR_PWR 0x02 +#define FBR_PWR_SPS (1<<0) /* support power selection */ +#define FBR_PWR_EPS (1<<1) /* enable low power selection */ +#define SD_IO_FBR_CIS 0x09 /* 0x109-0x10b */ +#define SD_IO_FBR_CSA 0x0c /* 0x10c-0x10e */ +#define SD_IO_FBR_DATA 0x0f +#define SD_IO_FBR_BLOCKLEN 0x10 /* 0x110-0x111 */ /* Card Information Structure (CIS) */ #define SD_IO_CIS_START 0x01000 @@ -131,5 +163,6 @@ #define SD_IO_SFIC_PHS 0x6 #define SD_IO_SFIC_WLAN 0x7 #define SD_IO_SFIC_ATA 0x8 /* Embedded SDIO-ATA */ +#define SD_IO_SFIC_EXTENDED 0xf /* See next byte */ #endif /* _SDMMC_IOREG_H_ */ Index: src/sys/dev/sdmmc/sdmmcvar.h diff -u src/sys/dev/sdmmc/sdmmcvar.h:1.30 src/sys/dev/sdmmc/sdmmcvar.h:1.31 --- src/sys/dev/sdmmc/sdmmcvar.h:1.30 Mon Feb 25 19:28:00 2019 +++ src/sys/dev/sdmmc/sdmmcvar.h Sun Sep 1 05:45:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmcvar.h,v 1.30 2019/02/25 19:28:00 jmcneill Exp $ */ +/* $NetBSD: sdmmcvar.h,v 1.31 2019/09/01 05:45:42 mlelstv Exp $ */ /* $OpenBSD: sdmmcvar.h,v 1.13 2009/01/09 10:55:22 jsg Exp $ */ /* @@ -185,6 +185,7 @@ struct sdmmc_function { uint16_t rca; /* relative card address */ int interface; /* SD/MMC:0, SDIO:standard interface */ int width; /* bus width */ + u_int blklen; /* block length */ int flags; #define SFF_ERROR 0x0001 /* function is poo; ignore it */ #define SFF_SDHC 0x0002 /* SD High Capacity card */ @@ -356,14 +357,18 @@ void sdmmc_dump_data(const char *, void int sdmmc_io_enable(struct sdmmc_softc *); void sdmmc_io_scan(struct sdmmc_softc *); int sdmmc_io_init(struct sdmmc_softc *, struct sdmmc_function *); +int sdmmc_io_set_blocklen(struct sdmmc_softc *, struct sdmmc_function *, + int); uint8_t sdmmc_io_read_1(struct sdmmc_function *, int); uint16_t sdmmc_io_read_2(struct sdmmc_function *, int); uint32_t sdmmc_io_read_4(struct sdmmc_function *, int); int sdmmc_io_read_multi_1(struct sdmmc_function *, int, u_char *, int); +int sdmmc_io_read_region_1(struct sdmmc_function *, int, u_char *, int); void sdmmc_io_write_1(struct sdmmc_function *, int, uint8_t); void sdmmc_io_write_2(struct sdmmc_function *, int, uint16_t); void sdmmc_io_write_4(struct sdmmc_function *, int, uint32_t); int sdmmc_io_write_multi_1(struct sdmmc_function *, int, u_char *, int); +int sdmmc_io_write_region_1(struct sdmmc_function *, int, u_char *, int); int sdmmc_io_function_enable(struct sdmmc_function *); void sdmmc_io_function_disable(struct sdmmc_function *);