This controller doesn't claim to be SD Host Controller compliant, but
it almost is.  The only thing missing seems to be the capabilities
register.  The following diff, inspired by the Linux code, makes the
controller in my new x220 work.

You'll need my last commit to pcidevs for this to compile.

ok?

Index: pci/sdhc_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
retrieving revision 1.10
diff -u -p -r1.10 sdhc_pci.c
--- pci/sdhc_pci.c      7 Sep 2010 16:21:46 -0000       1.10
+++ pci/sdhc_pci.c      31 Jul 2011 15:34:44 -0000
@@ -62,6 +62,10 @@ sdhc_pci_match(struct device *parent, vo
            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC)
                return 1;
 
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)
+               return 1;
+
        return 0;
 }
 
@@ -79,6 +83,7 @@ sdhc_pci_attach(struct device *parent, s
        bus_space_tag_t iot;
        bus_space_handle_t ioh;
        bus_size_t size;
+       u_int32_t caps = 0;
 
        /* Some TI controllers needs special treatment. */
        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI &&
@@ -86,11 +91,19 @@ sdhc_pci_attach(struct device *parent, s
             pa->pa_function == 4)
                sdhc_takecontroller(pa);
 
-       /* ENE controllers break if set to 0V bus power */
+       /* ENE controllers break if set to 0V bus power. */
        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENE &&
            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD)
                sc->sc.sc_flags |= SDHC_F_NOPWR0;
 
+       /* Some RICOH controllers lack a capability register. */
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)
+               caps = (0x21 << SDHC_BASE_FREQ_SHIFT) |
+                       (0x21 << SDHC_TIMEOUT_FREQ_SHIFT) |
+                       SDHC_TIMEOUT_FREQ_UNIT | SDHC_VOLTAGE_SUPP_3_3V |
+                       SDHC_DMA_SUPPORT;
+
        if (pci_intr_map(pa, &ih)) {
                printf(": can't map interrupt\n");
                return;
@@ -136,7 +149,7 @@ sdhc_pci_attach(struct device *parent, s
                        continue;
                }
 
-               if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma) != 0)
+               if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, caps) != 0)
                        /* XXX: sc->sc_host leak */
                        printf("%s at 0x%x: can't initialize host\n",
                            sc->sc.sc_dev.dv_xname, reg);
Index: sdmmc/sdhc.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhc.c,v
retrieving revision 1.33
diff -u -p -r1.33 sdhc.c
--- sdmmc/sdhc.c        7 Sep 2010 16:21:46 -0000       1.33
+++ sdmmc/sdhc.c        31 Jul 2011 15:34:44 -0000
@@ -129,11 +129,10 @@ struct cfdriver sdhc_cd = {
  */
 int
 sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
-    bus_space_handle_t ioh, bus_size_t iosize, int usedma)
+    bus_space_handle_t ioh, bus_size_t iosize, int usedma, u_int32_t caps)
 {
        struct sdmmcbus_attach_args saa;
        struct sdhc_host *hp;
-       u_int32_t caps;
        int error = 1;
 #ifdef SDHC_DEBUG
        u_int16_t version;
@@ -167,7 +166,8 @@ sdhc_host_found(struct sdhc_softc *sc, b
        (void)sdhc_host_reset(hp);
 
        /* Determine host capabilities. */
-       caps = HREAD4(hp, SDHC_CAPABILITIES);
+       if (caps == 0)
+               caps = HREAD4(hp, SDHC_CAPABILITIES);
 
        /* Use DMA if the host system and the controller support it. */
        if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
Index: sdmmc/sdhcvar.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhcvar.h,v
retrieving revision 1.5
diff -u -p -r1.5 sdhcvar.h
--- sdmmc/sdhcvar.h     7 Sep 2010 16:21:46 -0000       1.5
+++ sdmmc/sdhcvar.h     31 Jul 2011 15:34:44 -0000
@@ -32,7 +32,7 @@ struct sdhc_softc {
 
 /* Host controller functions called by the attachment driver. */
 int    sdhc_host_found(struct sdhc_softc *, bus_space_tag_t,
-           bus_space_handle_t, bus_size_t, int);
+           bus_space_handle_t, bus_size_t, int, u_int32_t);
 int    sdhc_activate(struct device *, int);
 void   sdhc_shutdown(void *);
 int    sdhc_intr(void *);

Reply via email to