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 *);