Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Added Ricoh 5U822/5U823 SD/MMC Controller support.



details:   https://anonhg.NetBSD.org/src/rev/6ac2b4a9cd1d
branches:  trunk
changeset: 777741:6ac2b4a9cd1d
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Fri Mar 02 18:20:33 2012 +0000

description:
Added Ricoh 5U822/5U823 SD/MMC Controller support.

diffstat:

 sys/dev/pci/sdhc_pci.c  |   80 +++++++++++++++++++++++++++++------
 sys/dev/sdmmc/sdhc.c    |  109 ++++++++++++++++++++++++++---------------------
 sys/dev/sdmmc/sdhcreg.h |    9 +++-
 3 files changed, 133 insertions(+), 65 deletions(-)

diffs (truncated from 523 to 300 lines):

diff -r f96c893317f7 -r 6ac2b4a9cd1d sys/dev/pci/sdhc_pci.c
--- a/sys/dev/pci/sdhc_pci.c    Fri Mar 02 18:11:59 2012 +0000
+++ b/sys/dev/pci/sdhc_pci.c    Fri Mar 02 18:20:33 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc_pci.c,v 1.6 2012/02/02 22:49:17 nonaka Exp $      */
+/*     $NetBSD: sdhc_pci.c,v 1.7 2012/03/02 18:20:33 nonaka Exp $      */
 /*     $OpenBSD: sdhc_pci.c,v 1.7 2007/10/30 18:13:45 chl Exp $        */
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.6 2012/02/02 22:49:17 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.7 2012/03/02 18:20:33 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -79,9 +79,10 @@
        u_int                   function;
 
        uint32_t                flags;
-#define        SDHC_PCI_QUIRK_FORCE_DMA        (1U << 0)
-#define        SDHC_PCI_QUIRK_TI_HACK          (1U << 1)
-#define        SDHC_PCI_QUIRK_NO_PWR0          (1U << 2)
+#define        SDHC_PCI_QUIRK_FORCE_DMA                (1U << 0)
+#define        SDHC_PCI_QUIRK_TI_HACK                  (1U << 1)
+#define        SDHC_PCI_QUIRK_NO_PWR0                  (1U << 2)
+#define        SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK    (1U << 3)
 } sdhc_pci_quirk_table[] = {
        {
                PCI_VENDOR_TI,
@@ -109,9 +110,19 @@
                0,
                SDHC_PCI_QUIRK_NO_PWR0
        },
+
+       {
+               PCI_VENDOR_RICOH,
+               PCI_PRODUCT_RICOH_Rx5U823,
+               0xffff,
+               0xffff,
+               0,
+               SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK
+       },
 };
 
 static void sdhc_pci_quirk_ti_hack(struct pci_attach_args *);
+static void sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *);
 
 static uint32_t
 sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa)
@@ -133,7 +144,7 @@
 
                        if ((q->subvendor == 0xffff)
                         && (q->subproduct == 0xffff))
-                               return q->flags;
+                               return (q->flags);
 
                        id = pci_conf_read(pa->pa_pc, pa->pa_tag,
                            PCI_SUBSYS_ID_REG);
@@ -144,18 +155,17 @@
                         && (q->subproduct != 0xffff)) {
                                if ((vendor == q->subvendor)
                                 && (product == q->subproduct))
-                                       return q->flags;
+                                       return (q->flags);
                        } else if (q->subvendor != 0xffff) {
                                if (product == q->subproduct)
-                                       return q->flags;
+                                       return (q->flags);
                        } else {
                                if (vendor == q->subvendor)
-                                       return q->flags;
+                                       return (q->flags);
                        }
                }
        }
-
-       return 0;
+       return (0);
 }
 
 static int
@@ -165,9 +175,12 @@
 
        if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SYSTEM &&
            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC)
-               return 1;
-
-       return 0;
+               return (1);
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
+           (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U822 ||
+            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U823))
+               return (1);
+       return (0);
 }
 
 static void
@@ -203,6 +216,8 @@
                SET(sc->sc.sc_flags, SDHC_FLAG_FORCE_DMA);
        if (ISSET(flags, SDHC_PCI_QUIRK_NO_PWR0))
                SET(sc->sc.sc_flags, SDHC_FLAG_NO_PWR0);
+       if (ISSET(flags, SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK))
+               sdhc_pci_quirk_ricoh_lower_freq_hack(pa);
 
        /*
         * Map and attach all hosts supported by the host controller.
@@ -276,6 +291,17 @@
                free(sc->sc.sc_host, M_DEVBUF);
 }
 
+static void
+sdhc_pci_conf_write(struct pci_attach_args *pa, int reg, uint8_t val)
+{
+       pcireg_t r;
+
+       r = pci_conf_read(pa->pa_pc, pa->pa_tag, reg & ~0x3);
+       r &= ~(0xff << ((reg & 0x3) * 8));
+       r |= (val << ((reg & 0x3) * 8));
+       pci_conf_write(pa->pa_pc, pa->pa_tag, reg & ~0x3, r);
+}
+
 /* TI specific register */
 #define SDHC_PCI_GENERAL_CTL           0x4c
 #define  MMC_SD_DIS                    0x02
@@ -309,3 +335,29 @@
        reg |= MMC_SD_DIS;
        pci_conf_write(pc, tag, SDHC_PCI_GENERAL_CTL, reg);
 }
+
+/* Ricoh specific register */
+#define SDHC_PCI_MODE_KEY              0xf9
+#define SDHC_PCI_MODE                  0x150
+#define  SDHC_PCI_MODE_SD20            0x10
+#define SDHC_PCI_BASE_FREQ_KEY         0xfc
+#define SDHC_PCI_BASE_FREQ             0xe1
+
+/* Some RICOH controllers need to be bumped into the right mode. */
+static void
+sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *pa)
+{
+
+       /* 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);
+}
diff -r f96c893317f7 -r 6ac2b4a9cd1d sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Fri Mar 02 18:11:59 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Fri Mar 02 18:20:33 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt Exp $   */
+/*     $NetBSD: sdhc.c,v 1.12 2012/03/02 18:20:33 nonaka Exp $ */
 /*     $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $        */
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.12 2012/03/02 18:20:33 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -79,6 +79,8 @@
        struct kmutex intr_mtx;
        struct kcondvar intr_cv;
 
+       int specver;                    /* spec. version */
+
        uint32_t flags;                 /* flags for this host */
 #define SHF_USE_DMA            0x0001
 #define SHF_USE_4BIT_MODE      0x0002
@@ -90,18 +92,18 @@
 static uint8_t
 hread1(struct sdhc_host *hp, bus_size_t reg)
 {
+
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
                return bus_space_read_1(hp->iot, hp->ioh, reg);
-
        return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 3));
 }
 
 static uint16_t
 hread2(struct sdhc_host *hp, bus_size_t reg)
 {
+
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
                return bus_space_read_2(hp->iot, hp->ioh, reg);
-
        return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 2));
 }
 
@@ -114,6 +116,7 @@
 static void
 hwrite1(struct sdhc_host *hp, bus_size_t o, uint8_t val)
 {
+
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
                bus_space_write_1(hp->iot, hp->ioh, o, val);
        } else {
@@ -128,6 +131,7 @@
 static void
 hwrite2(struct sdhc_host *hp, bus_size_t o, uint16_t val)
 {
+
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
                bus_space_write_2(hp->iot, hp->ioh, o, val);
        } else {
@@ -223,25 +227,29 @@
        struct sdmmcbus_attach_args saa;
        struct sdhc_host *hp;
        uint32_t caps;
-#ifdef SDHC_DEBUG
        uint16_t sdhcver;
 
        sdhcver = bus_space_read_2(iot, ioh, SDHC_HOST_CTL_VERSION);
-       aprint_normal_dev(sc->sc_dev, "SD Host Specification/Vendor Version ");
+       aprint_normal_dev(sc->sc_dev, "SD Host Specification ");
        switch (SDHC_SPEC_VERSION(sdhcver)) {
-       case 0x00:
-               aprint_normal("1.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
+       case SDHC_SPEC_VERS_100:
+               aprint_normal("1.0");
                break;
 
-       case 0x01:
-               aprint_normal("2.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
+       case SDHC_SPEC_VERS_200:
+               aprint_normal("2.0");
+               break;
+
+       case SDHC_SPEC_VERS_300:
+               aprint_normal("3.0");
                break;
 
        default:
-               aprint_normal(">2.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
+               aprint_normal("unknown version(0x%x)",
+                   SDHC_SPEC_VERSION(sdhcver));
                break;
        }
-#endif
+       aprint_normal(", rev.%u\n", SDHC_VENDOR_VERSION(sdhcver));
 
        /* Allocate one more host structure. */
        hp = malloc(sizeof(struct sdhc_host), M_DEVBUF, M_WAITOK|M_ZERO);
@@ -257,6 +265,7 @@
        hp->iot = iot;
        hp->ioh = ioh;
        hp->dmat = sc->sc_dmat;
+       hp->specver = SDHC_SPEC_VERSION(sdhcver);
 
        mutex_init(&hp->host_mtx, MUTEX_DEFAULT, IPL_SDMMC);
        mutex_init(&hp->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC);
@@ -285,12 +294,12 @@
        /*
         * Determine the base clock frequency. (2.2.24)
         */
-       if (SDHC_BASE_FREQ_KHZ(caps) != 0)
-               hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
+       hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
        if (hp->clkbase == 0) {
                if (sc->sc_clkbase == 0) {
                        /* The attachment driver must tell us. */
-                       aprint_error_dev(sc->sc_dev,"unknown base clock frequency\n");
+                       aprint_error_dev(sc->sc_dev,
+                           "unknown base clock frequency\n");
                        goto err;
                }
                hp->clkbase = sc->sc_clkbase;
@@ -419,6 +428,7 @@
 {
        struct sdhc_softc *sc = device_private(dev);
        struct sdhc_host *hp;
+       size_t i;
 
        /* XXX poll for command completion or suspend command
         * in progress */
@@ -427,15 +437,15 @@
        for (size_t n = 0; n < sc->sc_nhosts; n++) {
                hp = sc->sc_host[n];
                if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
-                       for (size_t i = 0; i < sizeof hp->regs; i += 4) {
+                       for (i = 0; i < sizeof hp->regs; i += 4) {
                                uint32_t v = HREAD4(hp, i);
-                               hp->regs[i+0] = (v >> 0);
-                               hp->regs[i+1] = (v >> 8);



Home | Main Index | Thread Index | Old Index