Source-Changes-HG archive

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

[src/trunk]: src/sys Support omap3 SDHC driver. tested on OVERO only.



details:   https://anonhg.NetBSD.org/src/rev/82fe27d14a17
branches:  trunk
changeset: 782343:82fe27d14a17
user:      kiyohara <kiyohara%NetBSD.org@localhost>
date:      Mon Oct 29 13:30:25 2012 +0000

description:
Support omap3 SDHC driver.  tested on OVERO only.

diffstat:

 sys/arch/arm/omap/omap3_sdhc.c     |  164 +++++++++++++++++++++++++++++++++++-
 sys/arch/arm/omap/omap3_sdmmcreg.h |   36 +++++++-
 sys/dev/sdmmc/sdhc.c               |   54 +++++++++--
 sys/dev/sdmmc/sdhcvar.h            |    9 +-
 4 files changed, 242 insertions(+), 21 deletions(-)

diffs (truncated from 449 to 300 lines):

diff -r 974a2c2cbc9a -r 82fe27d14a17 sys/arch/arm/omap/omap3_sdhc.c
--- a/sys/arch/arm/omap/omap3_sdhc.c    Mon Oct 29 13:19:15 2012 +0000
+++ b/sys/arch/arm/omap/omap3_sdhc.c    Mon Oct 29 13:30:25 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: omap3_sdhc.c,v 1.1 2012/07/12 03:08:26 matt Exp $      */
+/*     $NetBSD: omap3_sdhc.c,v 1.2 2012/10/29 13:30:25 kiyohara Exp $  */
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.1 2012/07/12 03:08:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.2 2012/10/29 13:30:25 kiyohara Exp $");
 
 #include "opt_omap.h"
 
@@ -48,8 +48,20 @@
 #include <dev/sdmmc/sdhcreg.h>
 #include <dev/sdmmc/sdhcvar.h>
 
+#define CLKD(kz)       (sc->sc.sc_clkbase / (kz))
+
+#define SDHC_READ(sc, reg) \
+       bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg))
+#define SDHC_WRITE(sc, reg, val) \
+       bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val))
+
 static int obiosdhc_match(device_t, cfdata_t, void *);
 static void obiosdhc_attach(device_t, device_t, void *);
+static int obiosdhc_detach(device_t, int);
+
+static int obiosdhc_rod(struct sdhc_softc *, int);
+static int obiosdhc_write_protect(struct sdhc_softc *);
+static int obiosdhc_card_detect(struct sdhc_softc *);
 
 struct obiosdhc_softc {
        struct sdhc_softc       sc;
@@ -61,7 +73,7 @@
 };
 
 CFATTACH_DECL_NEW(obiosdhc, sizeof(struct obiosdhc_softc),
-    obiosdhc_match, obiosdhc_attach, NULL, NULL);
+    obiosdhc_match, obiosdhc_attach, obiosdhc_detach, NULL);
 
 static int
 obiosdhc_match(device_t parent, cfdata_t cf, void *aux)
@@ -85,18 +97,26 @@
 {
        struct obiosdhc_softc * const sc = device_private(self);
        struct obio_attach_args * const oa = aux;
-       int error;
+       uint32_t clkd, stat;
+       int error, timo, clksft, n;
 
        sc->sc.sc_dmat = oa->obio_dmat;
        sc->sc.sc_dev = self;
        //sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
        sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
-       sc->sc.sc_flags |= SDHC_FLAG_HAVE_CGM;
        sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
+       sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
+       sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
        sc->sc.sc_host = sc->sc_hosts;
        sc->sc.sc_clkbase = 96000;      /* 96MHZ */
+       sc->sc.sc_clkmsk = 0x0000ffc0;
+       sc->sc.sc_vendor_rod = obiosdhc_rod;
+       sc->sc.sc_vendor_write_protect = obiosdhc_write_protect;
+       sc->sc.sc_vendor_card_detect = obiosdhc_card_detect;
        sc->sc_bst = oa->obio_iot;
 
+       clksft = ffs(sc->sc.sc_clkmsk) - 1;
+
        error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
            &sc->sc_bsh);
        if (error) {
@@ -111,7 +131,25 @@
        aprint_naive(": SDHC controller\n");
        aprint_normal(": SDHC controller\n");
 
-       sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL, 
+       /* XXXXXX: Turn-on regurator via I2C. */
+       /* XXXXXX: And enable ICLOCK/FCLOCK. */
+
+       /* MMCHS Soft reset */
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
+           SYSCONFIG_SOFTRESET);
+       timo = 3000000; /* XXXX 3 sec. */
+       while (timo--) {
+               if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) &
+                   SYSSTATUS_RESETDONE)
+                       break;
+               delay(1);
+       }
+       if (timo == 0)
+               aprint_error_dev(self, "Soft reset timeout\n");
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
+           SYSCONFIG_ENAWAKEUP | SYSCONFIG_AUTOIDLE);
+
+       sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL,
            sdhc_intr, &sc->sc);
        if (sc->sc_ih == NULL) {
                aprint_error_dev(self, "failed to establish interrupt %d\n",
@@ -128,6 +166,74 @@
                    error);
                goto fail;
        }
+
+       /* Set SDVS 1.8v and DTW 1bit mode */
+       SDHC_WRITE(sc, SDHC_HOST_CTL,
+           SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8));
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
+           bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_OD);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE |
+                                                       SDHC_SDCLK_ENABLE);
+       SDHC_WRITE(sc, SDHC_HOST_CTL,
+           SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
+
+       /*
+        * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start
+        * from 'OMAP35x Applications Processor  Technical Reference Manual'.
+        *
+        * During the INIT procedure, the MMCHS controller generates 80 clock
+        * periods. In order to keep the 1ms gap, the MMCHS controller should
+        * be configured to generate a clock whose frequency is smaller or
+        * equal to 80 KHz.
+        */
+
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
+       clkd = CLKD(80);
+       n = 1;
+       while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) {
+               clkd >>= 1;
+               n <<= 1;
+       }
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft));
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
+
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
+           bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT);
+       for (; n > 0; n--) {
+               SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000);
+               timo = 3000000; /* XXXX 3 sec. */
+               stat = 0;
+               while (!(stat & SDHC_COMMAND_COMPLETE)) {
+                       stat = SDHC_READ(sc, SDHC_NINTR_STATUS);
+                       if (--timo == 0)
+                               break;
+                       delay(1);
+               }
+               if (timo == 0) {
+                       aprint_error_dev(self, "INIT Procedure timeout\n");
+                       break;
+               }
+               SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat);
+       }
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
+           bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
+       SDHC_WRITE(sc, SDHC_CLOCK_CTL,
+           SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
+
        return;
 
 fail:
@@ -137,3 +243,49 @@
        }
        bus_space_unmap(sc->sc_bst, sc->sc_bsh, oa->obio_size);
 }
+
+static int
+obiosdhc_detach(device_t self, int flags)
+{
+//     struct obiosdhc_softc *sc = device_private(self);
+       int error;
+
+       error = config_detach_children(self, flags);
+
+       /* XXXXXX: Regurator turn-off via I2C. */
+       /* XXXXXX: And disable ICLOCK/FCLOCK. */
+
+       return error;
+}
+
+static int
+obiosdhc_rod(struct sdhc_softc *sc, int on)
+{
+       struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
+       uint32_t con;
+
+       con = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON);
+       if (on)
+               con |= CON_OD;
+       else
+               con &= ~CON_OD;
+       bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON, con);
+
+       return 0;
+}
+
+static int
+obiosdhc_write_protect(struct sdhc_softc *sc)
+{
+
+       /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
+       return 0;       /* XXXXXXX */
+}
+
+static int
+obiosdhc_card_detect(struct sdhc_softc *sc)
+{
+
+       /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
+       return 1;       /* XXXXXXXX */
+}
diff -r 974a2c2cbc9a -r 82fe27d14a17 sys/arch/arm/omap/omap3_sdmmcreg.h
--- a/sys/arch/arm/omap/omap3_sdmmcreg.h        Mon Oct 29 13:19:15 2012 +0000
+++ b/sys/arch/arm/omap/omap3_sdmmcreg.h        Mon Oct 29 13:30:25 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: omap3_sdmmcreg.h,v 1.1 2012/07/12 03:08:26 matt Exp $  */
+/*     $NetBSD: omap3_sdmmcreg.h,v 1.2 2012/10/29 13:30:25 kiyohara Exp $      */
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -37,4 +37,38 @@
 
 #define        OMAP3_SDMMC_SDHC_OFFSET 0x100
 #define        OMAP3_SDMMC_SDHC_SIZE   0x100
+
+#define MMCHS_SYSCONFIG                0x010   /* System Configuration */
+#  define SYSCONFIG_CLOCKACTIVITY_MASK (3 << 8)
+#  define SYSCONFIG_CLOCKACTIVITY_FCLK (2 << 8)
+#  define SYSCONFIG_CLOCKACTIVITY_ICLK (1 << 8)
+#  define SYSCONFIG_ENAWAKEUP          (1 << 2)
+#  define SYSCONFIG_SOFTRESET          (1 << 1)
+#  define SYSCONFIG_AUTOIDLE           (1 << 0)
+#define MMCHS_SYSSTATUS                0x014   /* System Status */
+#  define SYSSTATUS_RESETDONE          (1 << 0)
+#define MMCHS_CSRE             0x024   /* Card status response error */
+#define MMCHS_SYSTEST          0x028   /* System Test */
+#define MMCHS_CON              0x02c   /* Configuration */
+#  define CON_CLKEXTFREE               (1 << 16)
+#  define CON_PADEN                    (1 << 15)       /* Ctrl Pow for MMC */
+#  define CON_OBIE                     (1 << 14)       /* Out-of-Band Intr */
+#  define CON_OBIP                     (1 << 13)       /*O-of-B Intr Polarity*/
+#  define CON_CEATA                    (1 << 12)       /* CE-ATA */
+#  define CON_CTPL                     (1 << 11)       /* Ctrl Power dat[1] */
+#  define CON_DVAL_33US                        (0 << 9)        /* debounce filter val*/
+#  define CON_DVAL_231US               (1 << 9)        /* debounce filter val*/
+#  define CON_DVAL_1MS                 (2 << 9)        /* debounce filter val*/
+#  define CON_DVAL_8_4MS               (3 << 9)        /*   8.4ms */
+#  define CON_WPP                      (1 << 8)        /* Write protect pol */
+#  define CON_CDP                      (1 << 7)        /*Card detect polarity*/
+#  define CON_MIT                      (1 << 6)        /* MMC interrupt cmd */
+#  define CON_DW8                      (1 << 5)        /* 8-bit mode */
+#  define CON_MODE                     (1 << 4)        /* SYSTEST mode */
+#  define CON_STR                      (1 << 3)        /* Stream command */
+#  define CON_HR                       (1 << 2)        /* Broadcast host rsp */
+#  define CON_INIT                     (1 << 1)        /* Send init stream */
+#  define CON_OD                       (1 << 0)        /* Card open drain */
+#define MMCHS_PWCNT            0x030   /* Power counter */
+
 #endif
diff -r 974a2c2cbc9a -r 82fe27d14a17 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Mon Oct 29 13:19:15 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Mon Oct 29 13:30:25 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.31 2012/09/13 21:44:50 joerg Exp $  */
+/*     $NetBSD: sdhc.c,v 1.32 2012/10/29 13:30:25 kiyohara 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.31 2012/09/13 21:44:50 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.32 2012/10/29 13:30:25 kiyohara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -413,6 +413,8 @@
                        saa.saa_caps |= SMC_CAPS_MULTI_SEG_DMA;
                }
        }
+       if (ISSET(sc->sc_flags, SDHC_FLAG_SINGLE_ONLY))



Home | Main Index | Thread Index | Old Index