Newish Ricoh sdhc chipsets initialize into a high speed mode that is
not compatible with our existing sdmmc stack.  At activate we push
the chipset into the older modes; we need to do the same at resume
time.

Fixes the x230.

Index: sdhc_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 sdhc_pci.c
--- sdhc_pci.c  13 Jul 2014 23:10:23 -0000      1.15
+++ sdhc_pci.c  26 Sep 2014 10:27:40 -0000
@@ -48,17 +48,23 @@
 
 struct sdhc_pci_softc {
        struct sdhc_softc sc;
+       pci_chipset_tag_t sc_pc;
+       pcitag_t sc_tag;
+       pcireg_t sc_id;
        void *sc_ih;
 };
 
 int    sdhc_pci_match(struct device *, void *, void *);
 void   sdhc_pci_attach(struct device *, struct device *, void *);
+int    sdhc_pci_activate(struct device *, int);
+
+void   sdhc_pci_conf_write(pci_chipset_tag_t, pcitag_t, int, uint8_t);
 void   sdhc_takecontroller(struct pci_attach_args *);
-void   sdhc_pci_conf_write(struct pci_attach_args *, int, uint8_t);
+void   sdhc_ricohfix(struct sdhc_pci_softc *);
 
 struct cfattach sdhc_pci_ca = {
        sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach,
-       NULL, sdhc_activate
+       NULL, sdhc_pci_activate
 };
 
 int
@@ -105,6 +111,10 @@ sdhc_pci_attach(struct device *parent, s
        bus_size_t size;
        u_int32_t caps = 0;
 
+       sc->sc_pc = pa->pa_pc;
+       sc->sc_tag = pa->pa_tag;
+       sc->sc_id = pa->pa_id;
+
        /* Some TI controllers needs special treatment. */
        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI &&
            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD &&
@@ -118,20 +128,8 @@ sdhc_pci_attach(struct device *parent, s
 
        /* Some RICOH controllers need to be bumped into the right mode. */
        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
-           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823) {
-               /* Enable SD2.0 mode. */
-               sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0xfc);
-               sdhc_pci_conf_write(pa, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20);
-               sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0x00);
-
-               /*
-                * Some SD/MMC cards don't work with the default base
-                * clock frequency of 200MHz.  Lower it to 50Hz.
-                */
-               sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x01);
-               sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ, 50);
-               sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00);
-       }
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)
+               sdhc_ricohfix(sc);
 
        if (pci_intr_map(pa, &ih)) {
                printf(": can't map interrupt\n");
@@ -185,6 +183,27 @@ sdhc_pci_attach(struct device *parent, s
        }
 }
 
+int
+sdhc_pci_activate(struct device *self, int act)
+{
+       struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self;
+       int rv;
+
+       switch (act) {
+       case DVACT_SUSPEND:
+               rv = sdhc_activate(self, act);
+               break;
+       case DVACT_RESUME:
+               rv = sdhc_activate(self, act);
+               sdhc_ricohfix(sc);
+               break;
+       default:
+               rv = sdhc_activate(self, act);
+               break;
+       }
+       return (rv);
+}
+
 void
 sdhc_takecontroller(struct pci_attach_args *pa)
 {
@@ -207,12 +226,29 @@ sdhc_takecontroller(struct pci_attach_ar
 }
 
 void
-sdhc_pci_conf_write(struct pci_attach_args *pa, int reg, uint8_t val)
+sdhc_ricohfix(struct sdhc_pci_softc *sc)
+{
+       /* Enable SD2.0 mode. */
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0xfc);
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE, 
SDHC_PCI_MODE_SD20);
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0x00);
+
+       /*
+        * Some SD/MMC cards don't work with the default base
+        * clock frequency of 200MHz.  Lower it to 50Hz.
+        */
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 
0x01);
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ, 50);
+       sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 
0x00);
+}
+
+void
+sdhc_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val)
 {
        pcireg_t tmp;
 
-       tmp = pci_conf_read(pa->pa_pc, pa->pa_tag, reg & ~0x3);
+       tmp = pci_conf_read(pc, tag, reg & ~0x3);
        tmp &= ~(0xff << ((reg & 0x3) * 8));
        tmp |= (val << ((reg & 0x3) * 8));
-       pci_conf_write(pa->pa_pc, pa->pa_tag, reg & ~0x3, tmp);
+       pci_conf_write(pc, tag, reg & ~0x3, tmp);
 }

Reply via email to