The diff below adds (minimal) support for the 3.0 specification.  The
most important bit is support for the higher base clock and the larger
divisors that this standard brings.  It doesn't really add support for
the new features that allow faster data transport.

ok?


Index: sdhc.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhc.c,v
retrieving revision 1.40
diff -u -p -r1.40 sdhc.c
--- sdhc.c      10 Jan 2016 14:11:43 -0000      1.40
+++ sdhc.c      10 Jan 2016 15:01:41 -0000
@@ -42,6 +42,7 @@ struct sdhc_host {
        struct device *sdmmc;           /* generic SD/MMC device */
        bus_space_tag_t iot;            /* host register set tag */
        bus_space_handle_t ioh;         /* host register set handle */
+       u_int16_t version;              /* specification version */
        u_int clkbase;                  /* base clock frequency in KHz */
        int maxblklen;                  /* maximum block length */
        int flags;                      /* flags for this host */
@@ -133,6 +134,7 @@ sdhc_host_found(struct sdhc_softc *sc, b
        struct sdmmcbus_attach_args saa;
        struct sdhc_host *hp;
        int error = 1;
+       int max_clock;
 #ifdef SDHC_DEBUG
        u_int16_t version;
 
@@ -159,6 +161,9 @@ sdhc_host_found(struct sdhc_softc *sc, b
        hp->iot = iot;
        hp->ioh = ioh;
 
+       /* Store specification version. */
+       hp->version = bus_space_read_2(iot, ioh, SDHC_HOST_CTL_VERSION);
+
        /*
         * Reset the host controller and enable interrupts.
         */
@@ -175,15 +180,23 @@ sdhc_host_found(struct sdhc_softc *sc, b
        /*
         * Determine the base clock frequency. (2.2.24)
         */
-       if (SDHC_BASE_FREQ_KHZ(caps) != 0)
-               hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
+       if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
+               /* SDHC 3.0 supports 10-255 MHz. */
+               max_clock = 255000;
+               if (SDHC_BASE_FREQ_KHZ_V3(caps) != 0)
+                       hp->clkbase = SDHC_BASE_FREQ_KHZ_V3(caps);
+       } else {
+               /* SDHC 1.0/2.0 supports only 10-63 MHz. */
+               max_clock = 63000;
+               if (SDHC_BASE_FREQ_KHZ(caps) != 0)
+                       hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
+       }
        if (hp->clkbase == 0) {
                /* The attachment driver must tell us. */
                printf("%s: base clock frequency unknown\n",
                    sc->sc_dev.dv_xname);
                goto err;
-       } else if (hp->clkbase < 10000 || hp->clkbase > 63000) {
-               /* SDHC 1.0 supports only 10-63 MHz. */
+       } else if (hp->clkbase < 10000 || hp->clkbase > max_clock) {
                printf("%s: base clock frequency out of range: %u MHz\n",
                    sc->sc_dev.dv_xname, hp->clkbase / 1000);
                goto err;
@@ -443,9 +456,13 @@ sdhc_bus_power(sdmmc_chipset_handle_t sc
 static int
 sdhc_clock_divisor(struct sdhc_host *hp, u_int freq)
 {
+       int max_div = 256;
        int div;
 
-       for (div = 1; div <= 256; div *= 2)
+       if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3)
+               max_div = 2046;
+
+       for (div = 1; div <= max_div; div *= 2)
                if ((hp->clkbase / div) <= freq)
                        return (div / 2);
        /* No divisor found. */
@@ -462,6 +479,7 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sc
        struct sdhc_host *hp = sch;
        int s;
        int div;
+       int sdclk;
        int timo;
        int error = 0;
 
@@ -489,7 +507,11 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sc
                error = EINVAL;
                goto ret;
        }
-       HWRITE2(hp, SDHC_CLOCK_CTL, div << SDHC_SDCLK_DIV_SHIFT);
+       if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3)
+               sdclk = SDHC_SDCLK_DIV_V3(div);
+       else
+               sdclk = SDHC_SDCLK_DIV(div);
+       HWRITE2(hp, SDHC_CLOCK_CTL, sdclk);
 
        /*
         * Start internal clock.  Wait 10ms for stabilization.
Index: sdhcreg.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhcreg.h,v
retrieving revision 1.4
diff -u -p -r1.4 sdhcreg.h
--- sdhcreg.h   30 Jul 2006 17:20:40 -0000      1.4
+++ sdhcreg.h   10 Jan 2016 15:01:41 -0000
@@ -95,6 +95,8 @@
 #define SDHC_CLOCK_CTL                 0x2c
 #define  SDHC_SDCLK_DIV_SHIFT          8
 #define  SDHC_SDCLK_DIV_MASK           0xff
+#define  SDHC_SDCLK_DIV_RSHIFT_V3      2
+#define  SDHC_SDCLK_DIV_MASK_V3                0x300
 #define  SDHC_SDCLK_ENABLE             (1<<2)
 #define  SDHC_INTCLK_STABLE            (1<<1)
 #define  SDHC_INTCLK_ENABLE            (1<<0)
@@ -148,9 +150,11 @@
 #define  SDHC_MAX_BLK_LEN_MASK         0x3
 #define  SDHC_BASE_FREQ_SHIFT          8
 #define  SDHC_BASE_FREQ_MASK           0x3f
+#define  SDHC_BASE_FREQ_MASK_V3                0xff
 #define  SDHC_TIMEOUT_FREQ_UNIT                (1<<7)  /* 0=KHz, 1=MHz */
 #define  SDHC_TIMEOUT_FREQ_SHIFT       0
 #define  SDHC_TIMEOUT_FREQ_MASK                0x1f
+#define SDHC_CAPABILITIES_1            0x44
 #define SDHC_MAX_CAPABILITIES          0x48
 #define SDHC_SLOT_INTR_STATUS          0xfc
 #define SDHC_HOST_CTL_VERSION          0xfe
@@ -158,10 +162,22 @@
 #define  SDHC_SPEC_VERS_MASK           0xff
 #define  SDHC_VENDOR_VERS_SHIFT                8
 #define  SDHC_VENDOR_VERS_MASK         0xff
+#define  SDHC_SPEC_V1                  0
+#define  SDHC_SPEC_V2                  1
+#define  SDHC_SPEC_V3                  2
+
+/* SDHC_CLOCK_CTL encoding */
+#define SDHC_SDCLK_DIV(div)                                            \
+       (((div) & SDHC_SDCLK_DIV_MASK) << SDHC_SDCLK_DIV_SHIFT)
+#define SDHC_SDCLK_DIV_V3(div)                                         \
+       (SDHC_SDCLK_DIV(div) |                                          \
+       (((div) & SDHC_SDCLK_DIV_MASK_V3) >> SDHC_SDCLK_DIV_RSHIFT_V3))
 
 /* SDHC_CAPABILITIES decoding */
 #define SDHC_BASE_FREQ_KHZ(cap)                                                
\
        ((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK) * 1000)
+#define SDHC_BASE_FREQ_KHZ_V3(cap)                                     \
+       ((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK_V3) * 1000)
 #define SDHC_TIMEOUT_FREQ(cap)                                         \
        (((cap) >> SDHC_TIMEOUT_FREQ_SHIFT) & SDHC_TIMEOUT_FREQ_MASK)
 #define SDHC_TIMEOUT_FREQ_KHZ(cap)                                     \

Reply via email to