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 *);