Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic - Explicitly initialize CLKSRC register.



details:   https://anonhg.NetBSD.org/src/rev/a6060e8a5a38
branches:  trunk
changeset: 805291:a6060e8a5a38
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Dec 27 19:18:04 2014 +0000

description:
- Explicitly initialize CLKSRC register.
- Reset FIFO and DMA along with controller.
- Support chips with inverted PWREN logic.
- Enable RXDR and TXDR irqs.
- Set max clk based on supplied clock freq.
- Use external clk control as well as internal divisor to set clock rates.
  Requires bus glue to implement sc_set_clkdiv callback.

diffstat:

 sys/dev/ic/dwc_mmc.c     |  80 +++++++++++++++++++++++++++--------------------
 sys/dev/ic/dwc_mmc_reg.h |   7 +++-
 sys/dev/ic/dwc_mmc_var.h |   6 ++-
 3 files changed, 56 insertions(+), 37 deletions(-)

diffs (217 lines):

diff -r 9e9ab9ef79f2 -r a6060e8a5a38 sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c      Sat Dec 27 19:14:34 2014 +0000
+++ b/sys/dev/ic/dwc_mmc.c      Sat Dec 27 19:18:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc.c,v 1.1 2014/12/27 01:18:48 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.2 2014/12/27 19:18:04 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_dwc_mmc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.1 2014/12/27 01:18:48 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.2 2014/12/27 19:18:04 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -99,21 +99,21 @@
 
        dwc_mmc_host_reset(sc);
        dwc_mmc_bus_width(sc, 1);
-       dwc_mmc_bus_clock(sc, 400);
 
        memset(&saa, 0, sizeof(saa));
        saa.saa_busname = "sdmmc";
        saa.saa_sct = &dwc_mmc_chip_functions;
        saa.saa_sch = sc;
        saa.saa_clkmin = 400;
-       saa.saa_clkmax = 25000;
+       saa.saa_clkmax = sc->sc_clock_freq / 1000;
        saa.saa_caps = SMC_CAPS_4BIT_MODE|
                       SMC_CAPS_8BIT_MODE|
                       SMC_CAPS_SD_HIGHSPEED|
                       SMC_CAPS_MMC_HIGHSPEED|
                       SMC_CAPS_AUTO_STOP;
+       saa.saa_dmat = sc->sc_dmat;
+
 #if notyet
-       saa.saa_dmat = sc->sc_dmat;
        saa.saa_caps |= SMC_CAPS_DMA|
                        SMC_CAPS_MULTI_SEG_DMA;
 #endif
@@ -162,17 +162,24 @@
 dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq)
 {
        u_int pll_freq = sc->sc_clock_freq / 1000;
-       u_int n = howmany(pll_freq, freq) >> 1;
+       u_int clk_div, mmc_div;
+
+       mmc_div = min(howmany(pll_freq, freq), 0x3c);
+       clk_div = howmany(pll_freq / mmc_div, freq);
+       if (clk_div > 1 && (clk_div & 1) != 0)
+               clk_div++;
 
 #ifdef DWC_MMC_DEBUG
-       device_printf(sc->sc_dev, "%s: n=%u freq=%u\n",
-           __func__, n, n ? pll_freq / (2 * n) : pll_freq);
+       device_printf(sc->sc_dev, "%s: mmc_div=%u clk_div=%u freq=%u\n",
+           __func__, mmc_div, clk_div, pll_freq / mmc_div / clk_div);
 #endif
 
        MMC_WRITE(sc, DWC_MMC_CLKDIV_REG,
-           __SHIFTIN(n, DWC_MMC_CLKDIV_CLK_DIVIDER0));
+           __SHIFTIN(clk_div >> 1, DWC_MMC_CLKDIV_CLK_DIVIDER0));
+       if (dwc_mmc_update_clock(sc))
+               return ETIMEDOUT;
 
-       return dwc_mmc_update_clock(sc);
+       return sc->sc_set_clkdiv(sc, mmc_div);
 }
 
 static int
@@ -277,23 +284,30 @@
        uint32_t ctrl, fifoth;
        uint32_t rx_wmark, tx_wmark;
 
-       MMC_WRITE(sc, DWC_MMC_PWREN_REG, DWC_MMC_PWREN_POWER_ENABLE);
+       if (sc->sc_flags & DWC_MMC_F_PWREN_CLEAR) {
+               MMC_WRITE(sc, DWC_MMC_PWREN_REG, 0);
+       } else {
+               MMC_WRITE(sc, DWC_MMC_PWREN_REG, DWC_MMC_PWREN_POWER_ENABLE);
+       }
 
        MMC_WRITE(sc, DWC_MMC_CTRL_REG,
-           MMC_READ(sc, DWC_MMC_CTRL_REG) | DWC_MMC_CTRL_CONTROLLER_RESET);
+           MMC_READ(sc, DWC_MMC_CTRL_REG) | DWC_MMC_CTRL_RESET_ALL);
        while (--retry > 0) {
                ctrl = MMC_READ(sc, DWC_MMC_CTRL_REG);
-               if (ctrl & DWC_MMC_CTRL_CONTROLLER_RESET)
+               if ((ctrl & DWC_MMC_CTRL_RESET_ALL) == 0)
                        break;
                delay(100);
        }
 
-       MMC_WRITE(sc, DWC_MMC_TMOUT_REG, 0xffffffff);
+       MMC_WRITE(sc, DWC_MMC_CLKSRC_REG, 0);
+
+       MMC_WRITE(sc, DWC_MMC_TMOUT_REG, 0xffffff40);
        MMC_WRITE(sc, DWC_MMC_RINTSTS_REG, 0xffffffff);
 
        MMC_WRITE(sc, DWC_MMC_INTMASK_REG,
            DWC_MMC_INT_CD | DWC_MMC_INT_ACD | DWC_MMC_INT_DTO |
-           DWC_MMC_INT_ERROR | DWC_MMC_INT_CARDDET);
+           DWC_MMC_INT_ERROR | DWC_MMC_INT_CARDDET |
+           DWC_MMC_INT_RXDR | DWC_MMC_INT_TXDR);
 
        rx_wmark = (sc->sc_fifo_depth / 2) - 1;
        tx_wmark = sc->sc_fifo_depth / 2;
@@ -352,35 +366,28 @@
 dwc_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
 {
        struct dwc_mmc_softc *sc = sch;
-       uint32_t clkdiv, clkena;
+       uint32_t clkena;
 
 #ifdef DWC_MMC_DEBUG
        device_printf(sc->sc_dev, "%s: freq %d\n", __func__, freq);
 #endif
 
-       clkena = MMC_READ(sc, DWC_MMC_CLKENA_REG);
-       if (clkena & DWC_MMC_CLKENA_CCLK_ENABLE) {
-               clkena &= ~DWC_MMC_CLKENA_CCLK_ENABLE;
+       MMC_WRITE(sc, DWC_MMC_CLKENA_REG, 0);
+       if (dwc_mmc_update_clock(sc) != 0)
+               return ETIMEDOUT;
+
+       if (freq) {
+               if (dwc_mmc_set_clock(sc, freq) != 0)
+                       return EIO;
+
+               clkena = DWC_MMC_CLKENA_CCLK_ENABLE;
+               clkena |= DWC_MMC_CLKENA_CCLK_LOW_POWER; /* XXX SD/MMC only */
                MMC_WRITE(sc, DWC_MMC_CLKENA_REG, clkena);
                if (dwc_mmc_update_clock(sc) != 0)
                        return ETIMEDOUT;
        }
 
-       if (freq) {
-               clkdiv = MMC_READ(sc, DWC_MMC_CLKDIV_REG);
-               clkdiv &= ~DWC_MMC_CLKDIV_CLK_DIVIDER0;
-               if (dwc_mmc_update_clock(sc) != 0)
-                       return ETIMEDOUT;
-
-               if (dwc_mmc_set_clock(sc, freq) != 0)
-                       return EIO;
-
-               clkena |= DWC_MMC_CLKENA_CCLK_ENABLE;
-               clkena |= DWC_MMC_CLKENA_CCLK_LOW_POWER; /* XXX SD/MMC only */
-               MMC_WRITE(sc, DWC_MMC_CLKENA_REG, clkena);
-               if (dwc_mmc_update_clock(sc) != 0)
-                       return ETIMEDOUT;
-       }
+       delay(1000);
 
        return 0;
 }
@@ -423,6 +430,11 @@
        uint32_t cmdval = DWC_MMC_CMD_START_CMD;
        uint32_t ctrl;
 
+#ifdef DWC_MMC_DEBUG
+       device_printf(sc->sc_dev, "exec opcode=%d flags=%#x\n",
+           cmd->c_opcode, cmd->c_flags);
+#endif
+
        if (sc->sc_flags & DWC_MMC_F_USE_HOLD_REG)
                cmdval |= DWC_MMC_CMD_USE_HOLD_REG;
 
diff -r 9e9ab9ef79f2 -r a6060e8a5a38 sys/dev/ic/dwc_mmc_reg.h
--- a/sys/dev/ic/dwc_mmc_reg.h  Sat Dec 27 19:14:34 2014 +0000
+++ b/sys/dev/ic/dwc_mmc_reg.h  Sat Dec 27 19:18:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_reg.h,v 1.1 2014/12/27 01:18:48 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_reg.h,v 1.2 2014/12/27 19:18:04 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -32,6 +32,7 @@
 #define DWC_MMC_CTRL_REG                       0x0000
 #define DWC_MMC_PWREN_REG                      0x0004
 #define DWC_MMC_CLKDIV_REG                     0x0008
+#define DWC_MMC_CLKSRC_REG                     0x000c
 #define DWC_MMC_CLKENA_REG                     0x0010
 #define DWC_MMC_TMOUT_REG                      0x0014
 #define DWC_MMC_CTYPE_REG                      0x0018
@@ -69,6 +70,10 @@
 #define DWC_MMC_CTRL_DMA_RESET                 __BIT(2)
 #define DWC_MMC_CTRL_FIFO_RESET                        __BIT(1)
 #define DWC_MMC_CTRL_CONTROLLER_RESET          __BIT(0)
+#define DWC_MMC_CTRL_RESET_ALL \
+       (DWC_MMC_CTRL_CONTROLLER_RESET | \
+        DWC_MMC_CTRL_FIFO_RESET | \
+        DWC_MMC_CTRL_DMA_RESET)
 
 #define DWC_MMC_PWREN_POWER_ENABLE             __BIT(0)
 
diff -r 9e9ab9ef79f2 -r a6060e8a5a38 sys/dev/ic/dwc_mmc_var.h
--- a/sys/dev/ic/dwc_mmc_var.h  Sat Dec 27 19:14:34 2014 +0000
+++ b/sys/dev/ic/dwc_mmc_var.h  Sat Dec 27 19:18:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_var.h,v 1.1 2014/12/27 01:18:48 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_var.h,v 1.2 2014/12/27 19:18:04 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -38,7 +38,9 @@
        unsigned int            sc_clock_freq;
        unsigned int            sc_fifo_depth;
        uint32_t                sc_flags;
-#define DWC_MMC_F_USE_HOLD_REG 0x0001
+#define DWC_MMC_F_USE_HOLD_REG 0x0001  /* set USE_HOLD_REG with every cmd */
+#define DWC_MMC_F_PWREN_CLEAR  0x0002  /* clear POWER_ENABLE bit to enable */
+       int                     (*sc_set_clkdiv)(struct dwc_mmc_softc *, int);
 
        device_t                sc_sdmmc_dev;
        kmutex_t                sc_intr_lock;



Home | Main Index | Thread Index | Old Index