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

Reply via email to