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 basic UHS-I support. SDR50 and SDR104 are ...



details:   https://anonhg.NetBSD.org/src/rev/ac9be16a58f8
branches:  trunk
changeset: 339672:ac9be16a58f8
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Aug 02 21:44:36 2015 +0000

description:
Add basic UHS-I support. SDR50 and SDR104 are supported, but not DDR50.

diffstat:

 sys/dev/sdmmc/sdmmc_mem.c |  82 ++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/sdmmc/sdmmcchip.h |  12 ++++++-
 sys/dev/sdmmc/sdmmcreg.h  |   4 +-
 sys/dev/sdmmc/sdmmcvar.h  |   3 +-
 4 files changed, 90 insertions(+), 11 deletions(-)

diffs (228 lines):

diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_mem.c,v 1.34 2015/02/27 16:08:17 nonaka Exp $    */
+/*     $NetBSD: sdmmc_mem.c,v 1.35 2015/08/02 21:44:36 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.34 2015/02/27 16:08:17 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.35 2015/08/02 21:44:36 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -104,6 +104,7 @@
 {
        uint32_t host_ocr;
        uint32_t card_ocr;
+       uint32_t new_ocr;
        uint32_t ocr = 0;
        int error;
 
@@ -184,19 +185,78 @@
                error = sdmmc_mem_send_if_cond(sc, 0x1aa, &card_ocr);
                if (error == 0 && card_ocr == 0x1aa)
                        SET(ocr, MMC_OCR_HCS);
+
+               if (sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch) & MMC_OCR_S18A)
+                       SET(ocr, MMC_OCR_S18A);
        }
        host_ocr |= ocr;
 
        /* Send the new OCR value until all cards are ready. */
-       error = sdmmc_mem_send_op_cond(sc, host_ocr, NULL);
+       error = sdmmc_mem_send_op_cond(sc, host_ocr, &new_ocr);
        if (error) {
                DPRINTF(("%s: couldn't send memory OCR\n", SDMMCDEVNAME(sc)));
                goto out;
        }
 
+       if (ISSET(new_ocr, MMC_OCR_S18A) && sc->sc_sct->signal_voltage) {
+               /*
+                * Card and host support low voltage mode, begin switch
+                * sequence.
+                */
+               struct sdmmc_command cmd;
+               memset(&cmd, 0, sizeof(cmd));
+               cmd.c_arg = 0;
+               cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+               cmd.c_opcode = SD_VOLTAGE_SWITCH;
+               error = sdmmc_mmc_command(sc, &cmd);
+               if (error) {
+                       DPRINTF(("%s: voltage switch command failed\n",
+                           SDMMCDEVNAME(sc)));
+                       goto out;
+               }
+
+               delay(1000);
+
+               /*
+                * Stop the clock
+                */
+               error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch,
+                   SDMMC_SDCLK_OFF);
+               if (error)
+                       goto out;
+
+               delay(1000);
+
+               /*
+                * Card switch command was successful, update host controller
+                * signal voltage setting.
+                */
+               error = sdmmc_chip_signal_voltage(sc->sc_sct,
+                   sc->sc_sch, SDMMC_SIGNAL_VOLTAGE_180);
+               if (error)
+                       goto out;
+
+               delay(5000);
+
+               /*
+                * Switch to SDR12 timing
+                */
+               error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000);
+               if (error)
+                       goto out;
+
+               delay(1000);
+
+               SET(sc->sc_flags, SMF_UHS_MODE);
+       }
+
 out:
        SDMMC_UNLOCK(sc);
 
+       if (error)
+               printf("%s: %s failed with error %d\n", SDMMCDEVNAME(sc),
+                   __func__, error);
+
        return error;
 }
 
@@ -617,23 +677,26 @@
        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 },
+                 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 },
+                 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 },
+               { 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 },
+               { 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 },
+               { 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;
        sdmmc_bitfield512_t status; /* Switch Function Status */
@@ -684,6 +747,9 @@
                    i < __arraycount(switch_group0_functions); i++, g <<= 1) {
                        if (!(switch_group0_functions[i].v & host_ocr))
                                continue;
+                       if (switch_group0_functions[i].uhs &&
+                           !ISSET(sc->sc_flags, SMF_UHS_MODE))
+                               break;
                        if (g & support_func)
                                best_func = i;
                }
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcchip.h
--- a/sys/dev/sdmmc/sdmmcchip.h Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcchip.h Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcchip.h,v 1.4 2011/05/18 01:07:17 dyoung Exp $     */
+/*     $NetBSD: sdmmcchip.h,v 1.5 2015/08/02 21:44:36 jmcneill Exp $   */
 /*     $OpenBSD: sdmmcchip.h,v 1.3 2007/05/31 10:09:01 uwe Exp $       */
 
 /*
@@ -57,6 +57,9 @@
        /* card interrupt */
        void            (*card_enable_intr)(sdmmc_chipset_handle_t, int);
        void            (*card_intr_ack)(sdmmc_chipset_handle_t);
+
+       /* UHS functions */
+       int             (*signal_voltage)(sdmmc_chipset_handle_t, int);
 };
 
 /* host controller reset */
@@ -90,11 +93,18 @@
        ((tag)->card_enable_intr((handle), (enable)))
 #define sdmmc_chip_card_intr_ack(tag, handle)                          \
        ((tag)->card_intr_ack((handle)))
+/* UHS functions */
+#define sdmmc_chip_signal_voltage(tag, handle, voltage)                \
+       ((tag)->signal_voltage((handle), (voltage)))
 
 /* clock frequencies for sdmmc_chip_bus_clock() */
 #define SDMMC_SDCLK_OFF                0
 #define SDMMC_SDCLK_400K       400
 
+/* voltage levels for sdmmc_chip_signal_voltage() */
+#define SDMMC_SIGNAL_VOLTAGE_330       0
+#define SDMMC_SIGNAL_VOLTAGE_180       1
+
 /* SPI mode */
 struct sdmmc_spi_chip_functions {
        /* card initialize */
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h  Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h  Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcreg.h,v 1.15 2014/12/07 20:07:25 jmcneill Exp $   */
+/*     $NetBSD: sdmmcreg.h,v 1.16 2015/08/02 21:44:36 jmcneill Exp $   */
 /*     $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $        */
 
 /*
@@ -58,6 +58,7 @@
 #define SD_SEND_RELATIVE_ADDR          3       /* R6 */
 #define SD_SEND_SWITCH_FUNC            6       /* R1 */
 #define SD_SEND_IF_COND                        8       /* R7 */
+#define SD_VOLTAGE_SWITCH              11      /* R1 */
 
 /* SD application commands */                  /* response type */
 #define SD_APP_SET_BUS_WIDTH           6       /* R1 */
@@ -68,6 +69,7 @@
 /* OCR bits */
 #define MMC_OCR_MEM_READY              (1U<<31)/* memory power-up status bit */
 #define MMC_OCR_HCS                    (1<<30)
+#define MMC_OCR_S18A                   (1<<24)
 #define MMC_OCR_3_5V_3_6V              (1<<23)
 #define MMC_OCR_3_4V_3_5V              (1<<22)
 #define MMC_OCR_3_3V_3_4V              (1<<21)
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcvar.h
--- a/sys/dev/sdmmc/sdmmcvar.h  Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcvar.h  Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcvar.h,v 1.16 2015/02/27 16:08:17 nonaka Exp $     */
+/*     $NetBSD: sdmmcvar.h,v 1.17 2015/08/02 21:44:36 jmcneill Exp $   */
 /*     $OpenBSD: sdmmcvar.h,v 1.13 2009/01/09 10:55:22 jsg Exp $       */
 
 /*
@@ -216,6 +216,7 @@
 #define SMF_MEM_MODE           0x0008  /* host in memory mode (SD or MMC) */
 #define SMF_CARD_PRESENT       0x4000  /* card presence noticed */
 #define SMF_CARD_ATTACHED      0x8000  /* card driver(s) attached */
+#define SMF_UHS_MODE           0x10000 /* host in UHS mode */
 
        uint32_t sc_caps;               /* host capability */
 #define SMC_CAPS_AUTO_STOP     0x0001  /* send CMD12 automagically by host */



Home | Main Index | Thread Index | Old Index