Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic More or less a rewrite of dwc_mmc, based on awin_...



details:   https://anonhg.NetBSD.org/src/rev/ea7402e2a225
branches:  trunk
changeset: 824824:ea7402e2a225
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Jun 19 22:03:02 2017 +0000

description:
More or less a rewrite of dwc_mmc, based on awin_mmc, adding DMA support.

diffstat:

 sys/dev/ic/dwc_mmc.c     |  928 ++++++++++++++++++++++++++++------------------
 sys/dev/ic/dwc_mmc_reg.h |  309 +++++++--------
 sys/dev/ic/dwc_mmc_var.h |   63 ++-
 3 files changed, 737 insertions(+), 563 deletions(-)

diffs (truncated from 1546 to 300 lines):

diff -r 3bcc48c8fe63 -r ea7402e2a225 sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c      Mon Jun 19 22:01:18 2017 +0000
+++ b/sys/dev/ic/dwc_mmc.c      Mon Jun 19 22:03:02 2017 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: dwc_mmc.c,v 1.10 2015/12/27 18:35:29 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.11 2017/06/19 22:03:02 jmcneill Exp $ */
 
 /*-
- * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include "opt_dwc_mmc.h"
-
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.10 2015/12/27 18:35:29 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.11 2017/06/19 22:03:02 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,6 +43,8 @@
 #include <dev/ic/dwc_mmc_reg.h>
 #include <dev/ic/dwc_mmc_var.h>
 
+#define DWC_MMC_NDESC          64
+
 static int     dwc_mmc_host_reset(sdmmc_chipset_handle_t);
 static uint32_t        dwc_mmc_host_ocr(sdmmc_chipset_handle_t);
 static int     dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t);
@@ -55,25 +55,10 @@
 static int     dwc_mmc_bus_width(sdmmc_chipset_handle_t, int);
 static int     dwc_mmc_bus_rod(sdmmc_chipset_handle_t, int);
 static void    dwc_mmc_exec_command(sdmmc_chipset_handle_t,
-                                    struct sdmmc_command *);
+                                     struct sdmmc_command *);
 static void    dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
 static void    dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t);
 
-static int     dwc_mmc_set_clock(struct dwc_mmc_softc *, u_int);
-static int     dwc_mmc_update_clock(struct dwc_mmc_softc *);
-static int     dwc_mmc_wait_rint(struct dwc_mmc_softc *, uint32_t, int);
-static int     dwc_mmc_pio_wait(struct dwc_mmc_softc *,
-                                struct sdmmc_command *);
-static int     dwc_mmc_pio_transfer(struct dwc_mmc_softc *,
-                                    struct sdmmc_command *);
-
-#ifdef DWC_MMC_DEBUG
-static void    dwc_mmc_print_rint(struct dwc_mmc_softc *, const char *,
-                                  uint32_t);
-#endif
-
-void           dwc_mmc_dump_regs(int);
-
 static struct sdmmc_chip_functions dwc_mmc_chip_functions = {
        .host_reset = dwc_mmc_host_reset,
        .host_ocr = dwc_mmc_host_ocr,
@@ -89,23 +74,67 @@
        .card_intr_ack = dwc_mmc_card_intr_ack,
 };
 
-#define MMC_WRITE(sc, reg, val) \
+#define MMC_WRITE(sc, reg, val)        \
        bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
 #define MMC_READ(sc, reg) \
        bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
 
-void
-dwc_mmc_init(struct dwc_mmc_softc *sc)
+static void
+dwc_mmc_dump_regs(struct dwc_mmc_softc *sc)
 {
-       struct sdmmcbus_attach_args saa;
+       device_printf(sc->sc_dev, "device registers:\n");
+       for (u_int off = 0x00; off < 0x100; off += 16) {
+               device_printf(sc->sc_dev, "xxxxxx%02x: %08x %08x %08x %08x\n",
+                   off,
+                   MMC_READ(sc, off + 0), MMC_READ(sc, off + 4),
+                   MMC_READ(sc, off + 8), MMC_READ(sc, off + 12));
+       }
+}
+
+static int
+dwc_mmc_idma_setup(struct dwc_mmc_softc *sc)
+{
+       int error;
+
+       sc->sc_idma_xferlen = 0x1000;
 
-       mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
-       cv_init(&sc->sc_intr_cv, "dwcmmcirq");
+       sc->sc_idma_ndesc = DWC_MMC_NDESC;
+       sc->sc_idma_size = sizeof(struct dwc_mmc_idma_desc) *
+           sc->sc_idma_ndesc;
+       error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 8,
+           sc->sc_idma_size, sc->sc_idma_segs, 1,
+           &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
+       if (error)
+               return error;
+       error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
+           sc->sc_idma_nsegs, sc->sc_idma_size,
+           &sc->sc_idma_desc, BUS_DMA_WAITOK);
+       if (error)
+               goto free;
+       error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
+           sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
+       if (error)
+               goto unmap;
+       error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
+           sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
+       if (error)
+               goto destroy;
+       return 0;
 
-#ifdef DWC_MMC_DEBUG
-       const uint32_t verid = MMC_READ(sc, DWC_MMC_VERID_REG);
-       aprint_normal_dev(sc->sc_dev, "version 0x%04x\n", verid & 0xffff);
-#endif
+destroy:
+       bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
+unmap:
+       bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
+free:
+       bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
+       return error;
+}
+
+static void
+dwc_mmc_attach_i(device_t self)
+{
+       struct dwc_mmc_softc *sc = device_private(self);
+       struct sdmmcbus_attach_args saa;
 
        dwc_mmc_host_reset(sc);
        dwc_mmc_bus_width(sc, 1);
@@ -115,114 +144,27 @@
        saa.saa_sct = &dwc_mmc_chip_functions;
        saa.saa_sch = sc;
        saa.saa_clkmin = 400;
-       if (sc->sc_clock_max) {
-               saa.saa_clkmax = sc->sc_clock_max;
-       } else {
-               saa.saa_clkmax = sc->sc_clock_freq / 1000;
-       }
+       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;
-
-#if notyet
-       saa.saa_dmat = sc->sc_dmat;
-       saa.saa_caps |= SMC_CAPS_DMA|
-                       SMC_CAPS_MULTI_SEG_DMA;
-#endif
-
-       sc->sc_sdmmc_dev = config_found(sc->sc_dev, &saa, NULL);
-}
-
-int
-dwc_mmc_intr(void *priv)
-{
-       struct dwc_mmc_softc *sc = priv;
-       uint32_t mint, rint;
-
-       mutex_enter(&sc->sc_intr_lock);
-       rint = MMC_READ(sc, DWC_MMC_RINTSTS_REG);
-       mint = MMC_READ(sc, DWC_MMC_MINTSTS_REG);
-       if (!rint && !mint) {
-               mutex_exit(&sc->sc_intr_lock);
-               return 0;
+       if (ISSET(sc->sc_flags, DWC_MMC_F_DMA)) {
+               saa.saa_dmat = sc->sc_dmat;
+               saa.saa_caps |= SMC_CAPS_DMA |
+                               SMC_CAPS_MULTI_SEG_DMA;
        }
-       MMC_WRITE(sc, DWC_MMC_RINTSTS_REG, rint);
-       MMC_WRITE(sc, DWC_MMC_MINTSTS_REG, mint);
-
-#ifdef DWC_MMC_DEBUG
-       dwc_mmc_print_rint(sc, "irq", rint);
-#endif
-
-       if (rint & DWC_MMC_INT_CARDDET) {
-               rint &= ~DWC_MMC_INT_CARDDET;
-               if (sc->sc_sdmmc_dev) {
-                       sdmmc_needs_discover(sc->sc_sdmmc_dev);
-               }
-       }
-
-       if (rint) {
-               sc->sc_intr_rint |= rint;
-               cv_broadcast(&sc->sc_intr_cv);
-       }
-
-       mutex_exit(&sc->sc_intr_lock);
-
-       return 1;
-}
+       if (sc->sc_card_detect)
+               saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
 
-static int
-dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq)
-{
-       const u_int pll_freq = sc->sc_clock_freq / 1000;
-       const u_int clk_div = howmany(pll_freq, freq * 2);
-
-#ifdef DWC_MMC_DEBUG
-       printf("%s: using clk_div %d for freq %d (act %u)\n",
-           __func__, clk_div, freq, pll_freq / (clk_div * 2));
-#endif
-
-       MMC_WRITE(sc, DWC_MMC_CLKDIV_REG,
-           __SHIFTIN(clk_div, DWC_MMC_CLKDIV_CLK_DIVIDER0));
-       MMC_WRITE(sc, DWC_MMC_CLKSRC_REG, 0);   /* clock divider 0 */
-
-       return dwc_mmc_update_clock(sc);
-}
-
-static int
-dwc_mmc_update_clock(struct dwc_mmc_softc *sc)
-{
-       uint32_t cmd;
-       int retry;
-
-       cmd = DWC_MMC_CMD_START_CMD |
-             DWC_MMC_CMD_UPDATE_CLOCK_REGS_ONLY |
-             DWC_MMC_CMD_WAIT_PRVDATA_COMPLETE;
-
-       if (sc->sc_flags & DWC_MMC_F_USE_HOLD_REG)
-               cmd |= DWC_MMC_CMD_USE_HOLD_REG;
-
-       MMC_WRITE(sc, DWC_MMC_CMD_REG, cmd);
-       retry = 0xfffff;
-       while (--retry > 0) {
-               cmd = MMC_READ(sc, DWC_MMC_CMD_REG);
-               if ((cmd & DWC_MMC_CMD_START_CMD) == 0)
-                       break;
-               delay(10);
-       }
-
-       if (retry == 0) {
-               device_printf(sc->sc_dev, "timeout updating clock\n");
-               return ETIMEDOUT;
-       }
-
-       return 0;
+       sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
 }
 
 static int
 dwc_mmc_wait_rint(struct dwc_mmc_softc *sc, uint32_t mask, int timeout)
 {
+       const bool use_dma = ISSET(sc->sc_flags, DWC_MMC_F_DMA);
        int retry, error;
 
        KASSERT(mutex_owned(&sc->sc_intr_lock));
@@ -233,17 +175,254 @@
        retry = timeout / hz;
 
        while (retry > 0) {
-               error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz);
-               if (error && error != EWOULDBLOCK)
-                       return error;
-               if (sc->sc_intr_rint & mask)
-                       return 0;
+               if (use_dma) {
+                       error = cv_timedwait(&sc->sc_intr_cv,
+                           &sc->sc_intr_lock, hz);
+                       if (error && error != EWOULDBLOCK)
+                               return error;
+                       if (sc->sc_intr_rint & mask)
+                               return 0;
+               } else {
+                       sc->sc_intr_rint |= MMC_READ(sc, DWC_MMC_RINT);
+                       if (sc->sc_intr_rint & mask)
+                               return 0;
+                       delay(1000);
+               }
                --retry;
        }
 
        return ETIMEDOUT;
 }
 
+static void
+dwc_mmc_led(struct dwc_mmc_softc *sc, int on)
+{
+       if (sc->sc_set_led)
+               sc->sc_set_led(sc, on);
+}
+
+static int
+dwc_mmc_host_reset(sdmmc_chipset_handle_t sch)



Home | Main Index | Thread Index | Old Index