Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Add support for sampling clock tuning, require...
details: https://anonhg.NetBSD.org/src/rev/f3d2346ccc38
branches: trunk
changeset: 339716:f3d2346ccc38
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Wed Aug 05 10:29:37 2015 +0000
description:
Add support for sampling clock tuning, required for some UHS modes and
MMC HS200.
diffstat:
sys/dev/sdmmc/sdmmc_mem.c | 64 ++++++++++++++++++++++++++++++++++++++++------
sys/dev/sdmmc/sdmmcchip.h | 12 +++++++-
sys/dev/sdmmc/sdmmcreg.h | 4 ++-
3 files changed, 68 insertions(+), 12 deletions(-)
diffs (165 lines):
diff -r fbc7b38dfd16 -r f3d2346ccc38 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Wed Aug 05 07:34:56 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Wed Aug 05 10:29:37 2015 +0000
@@ -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 @@
/* 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 @@
}
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 @@
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 @@
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;
}
diff -r fbc7b38dfd16 -r f3d2346ccc38 sys/dev/sdmmc/sdmmcchip.h
--- a/sys/dev/sdmmc/sdmmcchip.h Wed Aug 05 07:34:56 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcchip.h Wed Aug 05 10:29:37 2015 +0000
@@ -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 @@
/* 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 @@
#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 @@
#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 */
diff -r fbc7b38dfd16 -r f3d2346ccc38 sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h Wed Aug 05 07:34:56 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h Wed Aug 05 10:29:37 2015 +0000
@@ -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 */
Home |
Main Index |
Thread Index |
Old Index