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) \