Module Name:    src
Committed By:   jmcneill
Date:           Wed Aug  5 10:29:37 UTC 2015

Modified Files:
        src/sys/dev/sdmmc: sdmmc_mem.c sdmmcchip.h sdmmcreg.h

Log Message:
Add support for sampling clock tuning, required for some UHS modes and
MMC HS200.


To generate a diff of this commit:
cvs rdiff -u -r1.44 -r1.45 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/sdmmc/sdmmcchip.h
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/sdmmc/sdmmcreg.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_mem.c
diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.44 src/sys/dev/sdmmc/sdmmc_mem.c:1.45
--- src/sys/dev/sdmmc/sdmmc_mem.c:1.44	Tue Aug  4 01:21:55 2015
+++ src/sys/dev/sdmmc/sdmmc_mem.c	Wed Aug  5 10:29:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmc_mem.c,v 1.44 2015/08/04 01:21:55 jmcneill Exp $	*/
+/*	$NetBSD: sdmmc_mem.c,v 1.45 2015/08/05 10:29:37 jmcneill Exp $	*/
 /*	$OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -45,7 +45,7 @@
 /* Routines for SD/MMC memory cards. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.44 2015/08/04 01:21:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.45 2015/08/05 10:29:37 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -142,13 +142,6 @@ sdmmc_mem_enable(struct sdmmc_softc *sc)
 	/* Reset memory (*must* do that before CMD55 or CMD1). */
 	sdmmc_go_idle_state(sc);
 
-	/* Set 3.3V signaling */
-	if (sc->sc_sct->signal_voltage) {
-		error = sdmmc_mem_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_330);
-		if (error)
-			goto out;
-	}
-
 	if (ISSET(sc->sc_caps, SMC_CAPS_SPI_MODE)) {
 		/* Check SD Ver.2 */
 		error = sdmmc_mem_send_if_cond(sc, 0x1aa, &card_ocr);
@@ -741,6 +734,44 @@ sdmmc_mem_select_transfer_mode(struct sd
 }
 
 static int
+sdmmc_mem_execute_tuning(struct sdmmc_softc *sc, struct sdmmc_function *sf)
+{
+	int timing = -1;
+
+	if (!ISSET(sc->sc_flags, SMF_UHS_MODE))
+		return 0;
+
+	if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
+		if (!ISSET(sc->sc_flags, SMF_UHS_MODE))
+			return 0;
+
+		switch (sf->csd.tran_speed) {
+		case 100000:
+			timing = SDMMC_TIMING_UHS_SDR50;
+			break;
+		case 208000:
+			timing = SDMMC_TIMING_UHS_SDR104;
+			break; 
+		default:
+			return 0;
+		}
+	} else {
+		switch (sf->csd.tran_speed) {
+		case 200000:
+			timing = SDMMC_TIMING_MMC_HS200;
+			break;
+		default:
+			return 0;
+		}
+	}
+
+	DPRINTF(("%s: execute tuning for timing %d\n", SDMMCDEVNAME(sc),
+	    timing));
+
+	return sdmmc_chip_execute_tuning(sc->sc_sct, sc->sc_sch, timing);
+}
+
+static int
 sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
 {
 	int support_func, best_func, bus_clock, error, i;
@@ -854,6 +885,13 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc
 	sc->sc_transfer_mode = switch_group0_functions[best_func].name;
 	sc->sc_busddr = ddr;
 
+	/* execute tuning (UHS) */
+	error = sdmmc_mem_execute_tuning(sc, sf);
+	if (error) {
+		aprint_error_dev(sc->sc_dev, "can't execute SD tuning\n");
+		return error;
+	}
+
 	return 0;
 }
 
@@ -994,6 +1032,14 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 
 		if (hs_timing == 2) {
 			sc->sc_transfer_mode = "HS200";
+
+			/* execute tuning (HS200) */
+			error = sdmmc_mem_execute_tuning(sc, sf);
+			if (error) {
+				aprint_error_dev(sc->sc_dev,
+				    "can't execute MMC tuning\n");
+				return error;
+			}
 		} else {
 			sc->sc_transfer_mode = NULL;
 		}

Index: src/sys/dev/sdmmc/sdmmcchip.h
diff -u src/sys/dev/sdmmc/sdmmcchip.h:1.6 src/sys/dev/sdmmc/sdmmcchip.h:1.7
--- src/sys/dev/sdmmc/sdmmcchip.h:1.6	Mon Aug  3 10:08:51 2015
+++ src/sys/dev/sdmmc/sdmmcchip.h	Wed Aug  5 10:29:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcchip.h,v 1.6 2015/08/03 10:08:51 jmcneill Exp $	*/
+/*	$NetBSD: sdmmcchip.h,v 1.7 2015/08/05 10:29:37 jmcneill Exp $	*/
 /*	$OpenBSD: sdmmcchip.h,v 1.3 2007/05/31 10:09:01 uwe Exp $	*/
 
 /*
@@ -61,6 +61,7 @@ struct sdmmc_chip_functions {
 	/* UHS functions */
 	int		(*signal_voltage)(sdmmc_chipset_handle_t, int);
 	int		(*bus_clock_ddr)(sdmmc_chipset_handle_t, int, bool);
+	int		(*execute_tuning)(sdmmc_chipset_handle_t, int);
 };
 
 /* host controller reset */
@@ -95,8 +96,10 @@ struct sdmmc_chip_functions {
 #define sdmmc_chip_card_intr_ack(tag, handle)				\
 	((tag)->card_intr_ack((handle)))
 /* UHS functions */
-#define sdmmc_chip_signal_voltage(tag, handle, voltage)		\
+#define sdmmc_chip_signal_voltage(tag, handle, voltage)			\
 	((tag)->signal_voltage((handle), (voltage)))
+#define sdmmc_chip_execute_tuning(tag, handle, timing)			\
+	((tag)->execute_tuning ? (tag)->execute_tuning((handle), (timing)) : EINVAL)
 
 /* clock frequencies for sdmmc_chip_bus_clock() */
 #define SDMMC_SDCLK_OFF		0
@@ -106,6 +109,11 @@ struct sdmmc_chip_functions {
 #define SDMMC_SIGNAL_VOLTAGE_330	0
 #define SDMMC_SIGNAL_VOLTAGE_180	1
 
+/* timings for sdmmc_chip_execute_tuning() */
+#define SDMMC_TIMING_UHS_SDR50		0
+#define SDMMC_TIMING_UHS_SDR104		1
+#define SDMMC_TIMING_MMC_HS200		2
+
 /* SPI mode */
 struct sdmmc_spi_chip_functions {
 	/* card initialize */

Index: src/sys/dev/sdmmc/sdmmcreg.h
diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.18 src/sys/dev/sdmmc/sdmmcreg.h:1.19
--- src/sys/dev/sdmmc/sdmmcreg.h:1.18	Mon Aug  3 10:08:51 2015
+++ src/sys/dev/sdmmc/sdmmcreg.h	Wed Aug  5 10:29:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcreg.h,v 1.18 2015/08/03 10:08:51 jmcneill Exp $	*/
+/*	$NetBSD: sdmmcreg.h,v 1.19 2015/08/05 10:29:37 jmcneill Exp $	*/
 /*	$OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -36,6 +36,8 @@
 #define MMC_SET_BLOCKLEN		16	/* R1 */
 #define MMC_READ_BLOCK_SINGLE		17	/* R1 */
 #define MMC_READ_BLOCK_MULTIPLE		18	/* R1 */
+#define MMC_SEND_TUNING_BLOCK		19	/* R1 */
+#define MMC_SEND_TUNING_BLOCK_HS200	21	/* R1 */
 #define MMC_SET_BLOCK_COUNT		23	/* R1 */
 #define MMC_WRITE_BLOCK_SINGLE		24	/* R1 */
 #define MMC_WRITE_BLOCK_MULTIPLE	25	/* R1 */

Reply via email to