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 DDR50 transfer modes.



details:   https://anonhg.NetBSD.org/src/rev/4fb1490a7f0f
branches:  trunk
changeset: 339688:4fb1490a7f0f
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Aug 03 10:08:51 2015 +0000

description:
Add support for DDR50 transfer modes.

diffstat:

 sys/dev/sdmmc/sdhc.c      |   36 +++++--
 sys/dev/sdmmc/sdmmc.c     |   10 +-
 sys/dev/sdmmc/sdmmc_io.c  |    7 +-
 sys/dev/sdmmc/sdmmc_mem.c |  205 ++++++++++++++++++++++++++++-----------------
 sys/dev/sdmmc/sdmmcchip.h |    7 +-
 sys/dev/sdmmc/sdmmcreg.h  |    8 +-
 sys/dev/sdmmc/sdmmcvar.h  |    9 +-
 7 files changed, 179 insertions(+), 103 deletions(-)

diffs (truncated from 607 to 300 lines):

diff -r c28953af5a7f -r 4fb1490a7f0f sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.75 2015/08/03 05:24:37 mlelstv Exp $        */
+/*     $NetBSD: sdhc.c,v 1.76 2015/08/03 10:08:51 jmcneill Exp $       */
 /*     $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $        */
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.75 2015/08/03 05:24:37 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.76 2015/08/03 10:08:51 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -174,7 +174,7 @@
 static int     sdhc_card_detect(sdmmc_chipset_handle_t);
 static int     sdhc_write_protect(sdmmc_chipset_handle_t);
 static int     sdhc_bus_power(sdmmc_chipset_handle_t, uint32_t);
-static int     sdhc_bus_clock(sdmmc_chipset_handle_t, int);
+static int     sdhc_bus_clock_ddr(sdmmc_chipset_handle_t, int, bool);
 static int     sdhc_bus_width(sdmmc_chipset_handle_t, int);
 static int     sdhc_bus_rod(sdmmc_chipset_handle_t, int);
 static void    sdhc_card_enable_intr(sdmmc_chipset_handle_t, int);
@@ -210,7 +210,7 @@
 
        /* bus power, clock frequency, width and ROD(OpenDrain/PushPull) */
        .bus_power = sdhc_bus_power,
-       .bus_clock = sdhc_bus_clock,
+       .bus_clock = NULL,      /* see sdhc_bus_clock_ddr */
        .bus_width = sdhc_bus_width,
        .bus_rod = sdhc_bus_rod,
 
@@ -223,6 +223,7 @@
 
        /* UHS functions */
        .signal_voltage = sdhc_signal_voltage,
+       .bus_clock_ddr = sdhc_bus_clock_ddr,
 };
 
 static int
@@ -418,14 +419,14 @@
                SET(hp->ocr, MMC_OCR_S18A);
                aprint_normal(" SDR50");
        }
-       if (ISSET(caps2, SDHC_SDR104_SUPP)) {
-               SET(hp->ocr, MMC_OCR_S18A);
-               aprint_normal(" SDR104");
-       }
        if (ISSET(caps2, SDHC_DDR50_SUPP)) {
                SET(hp->ocr, MMC_OCR_S18A);
                aprint_normal(" DDR50");
        }
+       if (ISSET(caps2, SDHC_SDR104_SUPP)) {
+               SET(hp->ocr, MMC_OCR_S18A);
+               aprint_normal(" SDR104 HS200");
+       }
        if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V)) {
                SET(hp->ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V);
                aprint_normal(" 1.8V");
@@ -534,6 +535,14 @@
                saa.saa_caps |= SMC_CAPS_8BIT_MODE;
        if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
                saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
+       if (ISSET(caps2, SDHC_SDR104_SUPP))
+               saa.saa_caps |= SMC_CAPS_UHS_SDR104 |
+                               SMC_CAPS_UHS_SDR50 |
+                               SMC_CAPS_MMC_HS200;
+       if (ISSET(caps2, SDHC_SDR50_SUPP))
+               saa.saa_caps |= SMC_CAPS_UHS_SDR50;
+       if (ISSET(caps2, SDHC_DDR50_SUPP))
+               saa.saa_caps |= SMC_CAPS_UHS_DDR50;
        if (ISSET(hp->flags, SHF_USE_DMA)) {
                saa.saa_caps |= SMC_CAPS_DMA;
                if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED))
@@ -964,7 +973,7 @@
  * Return zero on success.
  */
 static int
-sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
+sdhc_bus_clock_ddr(sdmmc_chipset_handle_t sch, int freq, bool ddr)
 {
        struct sdhc_host *hp = (struct sdhc_host *)sch;
        u_int div;
@@ -1007,14 +1016,19 @@
        }
 
        if (hp->specver >= SDHC_SPEC_VERS_300) {
-               /* XXX DDR */
                HCLR2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_MASK);
                if (freq > 100000) {
                        HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR104);
                } else if (freq > 50000) {
                        HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR50);
                } else if (freq > 25000) {
-                       HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR25);
+                       if (ddr) {
+                               HSET2(hp, SDHC_HOST_CTL2,
+                                   SDHC_UHS_MODE_SELECT_DDR50);
+                       } else {
+                               HSET2(hp, SDHC_HOST_CTL2,
+                                   SDHC_UHS_MODE_SELECT_SDR25);
+                       }
                } else if (freq > 400) {
                        HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR12);
                }
diff -r c28953af5a7f -r 4fb1490a7f0f sys/dev/sdmmc/sdmmc.c
--- a/sys/dev/sdmmc/sdmmc.c     Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc.c     Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc.c,v 1.28 2015/08/03 05:32:50 mlelstv Exp $       */
+/*     $NetBSD: sdmmc.c,v 1.29 2015/08/03 10:08:51 jmcneill 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.28 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.29 2015/08/03 10:08:51 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -523,7 +523,8 @@
        /*
         * Select the minimum clock frequency.
         */
-       error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_400K);
+       error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_400K,
+           false);
        if (error) {
                aprint_error_dev(sc->sc_dev, "couldn't supply clock\n");
                goto out;
@@ -569,7 +570,8 @@
 
        /* Turn off bus power and clock. */
        (void)sdmmc_chip_bus_width(sc->sc_sct, sc->sc_sch, 1);
-       (void)sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_OFF);
+       (void)sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_OFF,
+           false);
        (void)sdmmc_chip_bus_power(sc->sc_sct, sc->sc_sch, 0);
        sc->sc_busclk = sc->sc_clkmax;
 }
diff -r c28953af5a7f -r 4fb1490a7f0f sys/dev/sdmmc/sdmmc_io.c
--- a/sys/dev/sdmmc/sdmmc_io.c  Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_io.c  Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_io.c,v 1.9 2015/08/03 05:32:50 mlelstv Exp $     */
+/*     $NetBSD: sdmmc_io.c,v 1.10 2015/08/03 10:08:51 jmcneill 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.9 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.10 2015/08/03 10:08:51 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -231,7 +231,8 @@
                if (sc->sc_busclk > sf->csd.tran_speed)
                        sc->sc_busclk = sf->csd.tran_speed;
                error =
-                   sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, sc->sc_busclk);
+                   sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, sc->sc_busclk,
+                       false);
                if (error)
                        aprint_error_dev(sc->sc_dev,
                            "can't change bus clock\n");
diff -r c28953af5a7f -r 4fb1490a7f0f sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_mem.c,v 1.38 2015/08/03 05:32:50 mlelstv Exp $   */
+/*     $NetBSD: sdmmc_mem.c,v 1.39 2015/08/03 10:08:51 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.38 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.39 2015/08/03 10:08:51 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -96,6 +96,27 @@
 static int sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
     uint32_t, u_char *, size_t);
 
+static const struct {
+       const char *name;
+       int v;
+       int freq;
+} switch_group0_functions[] = {
+       /* Default/SDR12 */
+       { "Default/SDR12",       0,                      25000 },
+
+       /* High-Speed/SDR25 */
+       { "High-Speed/SDR25",   SMC_CAPS_SD_HIGHSPEED,   50000 },
+
+       /* SDR50 */
+       { "SDR50",              SMC_CAPS_UHS_SDR50,     100000 },
+
+       /* SDR104 */
+       { "SDR104",             SMC_CAPS_UHS_SDR104,    208000 },
+
+       /* DDR50 */
+       { "DDR50",              SMC_CAPS_UHS_DDR50,      50000 },
+};
+
 /*
  * Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
  */
@@ -221,7 +242,7 @@
                 * Stop the clock
                 */
                error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch,
-                   SDMMC_SDCLK_OFF);
+                   SDMMC_SDCLK_OFF, false);
                if (error)
                        goto out;
 
@@ -241,7 +262,8 @@
                /*
                 * Switch to SDR12 timing
                 */
-               error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000);
+               error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000,
+                   false);
                if (error)
                        goto out;
 
@@ -672,38 +694,39 @@
 }
 
 static int
+sdmmc_mem_select_transfer_mode(struct sdmmc_softc *sc, int support_func)
+{
+       if (ISSET(sc->sc_flags, SMF_UHS_MODE)) {
+               if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR104) &&
+                   ISSET(support_func, SD_ACCESS_MODE_SDR104)) {
+                       return SD_ACCESS_MODE_SDR104;
+               }
+               if (ISSET(sc->sc_caps, SMC_CAPS_UHS_DDR50) &&
+                   ISSET(support_func, SD_ACCESS_MODE_DDR50)) {
+                       return SD_ACCESS_MODE_DDR50;
+               }
+               if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR50) &&
+                   ISSET(support_func, SD_ACCESS_MODE_SDR50)) {
+                       return SD_ACCESS_MODE_SDR50;
+               }
+       }
+       if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) &&
+           ISSET(support_func, SD_ACCESS_MODE_SDR25)) {
+               return SD_ACCESS_MODE_SDR25;
+       }
+       return SD_ACCESS_MODE_SDR12;
+}
+
+static int
 sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
 {
-       static const struct {
-               int v;
-               int freq;
-               int uhs;
-       } switch_group0_functions[] = {
-               /* Default/SDR12 */
-               { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V |
-                 MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V,         25000, 0 },
-
-               /* High-Speed/SDR25 */
-               { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V |
-                 MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V,         50000, 0 },
-
-               /* SDR50 */
-               { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V,        100000, 1 },
-
-               /* SDR104 */
-               { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V,        208000, 1 },
-
-#if notyet
-               /* DDR50 */
-               { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V,         50000, 1 },
-#endif
-       };
-       int host_ocr, support_func, best_func, bus_clock, error, g, i;
+       int support_func, best_func, bus_clock, error, i;
        sdmmc_bitfield512_t status; /* Switch Function Status */
+       bool ddr = false;
 
        /* change bus clock */



Home | Main Index | Thread Index | Old Index