Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/omap Add a driver for the Enhanced Direct Memor...



details:   https://anonhg.NetBSD.org/src/rev/91304fde620e
branches:  trunk
changeset: 807589:91304fde620e
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Tue Apr 14 18:37:43 2015 +0000

description:
Add a driver for the Enhanced Direct Memory Access controller found
in the AM335x SoC. Written by Jared D. McNeill, with some final debug
by me.
Supports only DMA (not QDMA) yet, and there's no support for DMA event
matrix yet (this means that only primary DMA events can be used)

diffstat:

 sys/arch/arm/omap/files.omap2     |    8 +-
 sys/arch/arm/omap/omap2_obio.c    |    9 +-
 sys/arch/arm/omap/omap2_obiovar.h |    3 +-
 sys/arch/arm/omap/omap2_reg.h     |   19 +-
 sys/arch/arm/omap/omap_edma.c     |  578 ++++++++++++++++++++++++++++++++++++++
 sys/arch/arm/omap/omap_edma.h     |  173 +++++++++++
 6 files changed, 782 insertions(+), 8 deletions(-)

diffs (truncated from 882 to 300 lines):

diff -r 6d7424328de2 -r 91304fde620e sys/arch/arm/omap/files.omap2
--- a/sys/arch/arm/omap/files.omap2     Tue Apr 14 18:34:29 2015 +0000
+++ b/sys/arch/arm/omap/files.omap2     Tue Apr 14 18:37:43 2015 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.omap2,v 1.29 2014/08/22 19:44:04 jakllsch Exp $
+#      $NetBSD: files.omap2,v 1.30 2015/04/14 18:37:43 bouyer Exp $
 #
 # Configuration info for Texas Instruments OMAP2/OMAP3 CPU support
 # Based on xscale/files.pxa2x0
@@ -32,7 +32,7 @@
 defflag opt_omap.h                             TI_DM37XX: OMAP3
 
 # OBIO just an attach point
-device obio { [addr=-1], [size=0], [intr=-1], [mult=1], [intrbase=-1], [nobyteacc=0]
+device obio { [addr=-1], [size=0], [intr=-1], [mult=1], [intrbase=-1], [nobyteacc=0], [edmabase=-1]
             } : bus_space_generic
 attach obio at mainbus
 file   arch/arm/omap/omap2_obio.c              obio needs-count
@@ -170,6 +170,10 @@
 attach         omapdma at obio
 file   arch/arm/omap/omap3_sdma.c              omapdma needs-flag
 
+device edma
+attach edma at obio
+file   arch/arm/omap/omap_edma.c               edma needs-flag
+
 # these bus space methods are not bus-specific ...
 #
 file   arch/arm/omap/omap_nobyteacc_space.c    emifs | gpmc
diff -r 6d7424328de2 -r 91304fde620e sys/arch/arm/omap/omap2_obio.c
--- a/sys/arch/arm/omap/omap2_obio.c    Tue Apr 14 18:34:29 2015 +0000
+++ b/sys/arch/arm/omap/omap2_obio.c    Tue Apr 14 18:37:43 2015 +0000
@@ -1,7 +1,7 @@
-/*     $Id: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $ */
+/*     $Id: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $       */
 
 /* adapted from: */
-/*     $NetBSD: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $ */
+/*     $NetBSD: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $ */
 
 
 /*
@@ -103,7 +103,7 @@
 
 #include "opt_omap.h"
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $");
 
 #include "locators.h"
 #include "obio.h"
@@ -284,6 +284,7 @@
        oa.obio_size = cf->cf_loc[OBIOCF_SIZE];
        oa.obio_intr = cf->cf_loc[OBIOCF_INTR];
        oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE];
+       oa.obio_edmabase = cf->cf_loc[OBIOCF_EDMABASE];
 
 #if defined(OMAP2)
        if ((oa.obio_addr >= sc->sc_base)
@@ -351,6 +352,7 @@
        oa->obio_size = cf->cf_loc[OBIOCF_SIZE];
        oa->obio_intr = cf->cf_loc[OBIOCF_INTR];
        oa->obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE];
+       oa->obio_edmabase = cf->cf_loc[OBIOCF_EDMABASE];
 
        return config_match(parent, cf, oa);
 }
@@ -398,6 +400,7 @@
        { .name = "omapicu", .addr = 0x48200000, .required = true },
        { .name = "prcm", .addr = 0x44e00000, .required = true },
        { .name = "sitaracm", .addr = 0x44e10000, .required = true },
+       { .name = "edma", .addr = 0x49000000, .required = false },
 #endif
 #if defined(OMAP_3530)
        { .name = "omapdma", .addr = OMAP3530_SDMA_BASE, .required = true },
diff -r 6d7424328de2 -r 91304fde620e sys/arch/arm/omap/omap2_obiovar.h
--- a/sys/arch/arm/omap/omap2_obiovar.h Tue Apr 14 18:34:29 2015 +0000
+++ b/sys/arch/arm/omap/omap2_obiovar.h Tue Apr 14 18:37:43 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: omap2_obiovar.h,v 1.2 2012/09/05 00:19:59 matt Exp $ */
+/* $NetBSD: omap2_obiovar.h,v 1.3 2015/04/14 18:37:43 bouyer Exp $ */
 
 /*
  * Copyright (c) 2007 Microsoft
@@ -40,6 +40,7 @@
        bus_dma_tag_t   obio_dmat;
        unsigned int    obio_mult;
        unsigned int    obio_intrbase;
+       int             obio_edmabase;
 };
 
 struct obio_softc {
diff -r 6d7424328de2 -r 91304fde620e sys/arch/arm/omap/omap2_reg.h
--- a/sys/arch/arm/omap/omap2_reg.h     Tue Apr 14 18:34:29 2015 +0000
+++ b/sys/arch/arm/omap/omap2_reg.h     Tue Apr 14 18:37:43 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: omap2_reg.h,v 1.28 2014/07/20 23:08:43 bouyer Exp $ */
+/* $NetBSD: omap2_reg.h,v 1.29 2015/04/14 18:37:43 bouyer Exp $ */
 
 /*
  * Copyright (c) 2007 Microsoft
@@ -896,5 +896,20 @@
 #define        SDRAM_CONFIG_EBANK              __BIT(3)
 #define        SDRAM_CONFIG_PAGESIZE           __BITS(2,0)
 #endif
-       
+
+/* EDMA3 */
+#define AM335X_TPCC_BASE               0x49000000
+#define AM335X_TPCC_SIZE               0x00100000
+#define AM335X_TPTC0_BASE              0x49800000
+#define AM335X_TPTC0_SIZE              0x00100000
+#define AM335X_TPTC1_BASE              0x49900000
+#define AM335X_TPTC1_SIZE              0x00100000
+#define AM335X_TPTC2_BASE              0x49a00000
+#define AM335X_TPTC2_SIZE              0x00100000
+#define AM335X_INT_EDMACOMPINT         12
+#define AM335X_INT_EDMAMPERR           13
+#define AM335X_INT_EDMAERRINT          14
+#define AM335X_INT_TCERRINT0           112
+#define AM335X_INT_TCERRINT1           113
+#define AM335X_INT_TCERRINT2           114
 #endif /* _ARM_OMAP_OMAP2_REG_H_ */
diff -r 6d7424328de2 -r 91304fde620e sys/arch/arm/omap/omap_edma.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/omap/omap_edma.c     Tue Apr 14 18:37:43 2015 +0000
@@ -0,0 +1,578 @@
+/* $NetBSD: omap_edma.c,v 1.1 2015/04/14 18:37:43 bouyer Exp $ */
+
+/*-
+ * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_edma.c,v 1.1 2015/04/14 18:37:43 bouyer Exp $");
+
+#include "opt_omap.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/intr.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/bitops.h>
+
+#include <arm/omap/am335x_prcm.h>
+#include <arm/omap/omap2_prcm.h>
+#include <arm/omap/sitara_cm.h>
+#include <arm/omap/sitara_cmreg.h>
+
+#include <arm/omap/omap2_reg.h>
+#include <arm/omap/omap2_obiovar.h>
+#include <arm/omap/omap_edma.h>
+
+#ifdef TI_AM335X
+static const struct omap_module edma3cc_module =
+       { AM335X_PRCM_CM_PER, CM_PER_TPCC_CLKCTRL };
+static const struct omap_module edma3tc0_module =
+       { AM335X_PRCM_CM_PER, CM_PER_TPTC0_CLKCTRL };
+static const struct omap_module edma3tc1_module =
+       { AM335X_PRCM_CM_PER, CM_PER_TPTC1_CLKCTRL };
+static const struct omap_module edma3tc2_module =
+       { AM335X_PRCM_CM_PER, CM_PER_TPTC2_CLKCTRL };
+#endif
+
+#define NUM_DMA_CHANNELS       64
+#define NUM_PARAM_SETS         256
+#define MAX_PARAM_PER_CHANNEL  32
+
+#ifdef EDMA_DEBUG
+int edmadebug = 1;
+#define DPRINTF(n,s)    do { if ((n) <= edmadebug) device_printf s; } while (0)
+#else
+#define DPRINTF(n,s)    do {} while (0)
+#endif
+
+struct edma_softc;
+
+struct edma_channel {
+       struct edma_softc *ch_sc;
+       enum edma_type ch_type;
+       uint8_t ch_index;
+       void (*ch_callback)(void *);
+       void *ch_callbackarg;
+       unsigned int ch_nparams;
+};
+
+struct edma_softc {
+       device_t sc_dev;
+       bus_space_tag_t sc_iot;
+       bus_space_handle_t sc_ioh;
+       kmutex_t sc_lock;
+       struct edma_channel sc_dma[NUM_DMA_CHANNELS];
+
+       void *sc_ih;
+       void *sc_mperr_ih;
+       void *sc_errint_ih;
+
+       uint32_t sc_dmamask[NUM_DMA_CHANNELS / 32];
+       uint32_t sc_parammask[NUM_PARAM_SETS / 32];
+};
+
+static int edma_match(device_t, cfdata_t, void *);
+static void edma_attach(device_t, device_t, void *);
+
+static void edma_init(struct edma_softc *);
+static int edma_intr(void *);
+static int edma_mperr_intr(void *);
+static int edma_errint_intr(void *);
+static void edma_write_param(struct edma_softc *,
+                                 unsigned int, const struct edma_param *);
+static bool edma_bit_isset(uint32_t *, unsigned int);
+static void edma_bit_set(uint32_t *, unsigned int);
+static void edma_bit_clr(uint32_t *, unsigned int);
+
+CFATTACH_DECL_NEW(edma, sizeof(struct edma_softc),
+    edma_match, edma_attach, NULL, NULL);
+
+#define EDMA_READ(sc, reg) \
+       bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define EDMA_WRITE(sc, reg, val) \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+static int
+edma_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct obio_attach_args *obio = aux;
+
+#ifdef TI_AM335X
+       if (obio->obio_addr == AM335X_TPCC_BASE &&
+           obio->obio_size == AM335X_TPCC_SIZE &&
+           obio->obio_intrbase == AM335X_INT_EDMACOMPINT)
+               return 1;
+#endif
+
+       return 0;
+}
+
+static void
+edma_attach(device_t parent, device_t self, void *aux)
+{
+       struct edma_softc *sc = device_private(self);
+       struct obio_attach_args *obio = aux;
+       int idx;
+
+       sc->sc_dev = self;
+       sc->sc_iot = obio->obio_iot;
+       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
+       if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size,
+           0, &sc->sc_ioh) != 0) {
+               aprint_error(": couldn't map address spcae\n");
+               return;
+       }
+
+       aprint_normal("\n");
+       aprint_naive("\n");
+
+       for (idx = 0; idx < NUM_DMA_CHANNELS; idx++) {
+               struct edma_channel *ch = &sc->sc_dma[idx];
+               ch->ch_sc = sc;
+               ch->ch_type = EDMA_TYPE_DMA;
+               ch->ch_index = idx;
+               ch->ch_callback = NULL;
+               ch->ch_callbackarg = NULL;
+               ch->ch_nparams = 0;
+       }
+
+       edma_init(sc);
+
+       sc->sc_ih = intr_establish(obio->obio_intrbase + 0,
+           IPL_SCHED, IST_LEVEL, edma_intr, sc);
+       KASSERT(sc->sc_ih != NULL);
+
+       sc->sc_mperr_ih = intr_establish(obio->obio_intrbase + 1,
+           IPL_SCHED, IST_LEVEL, edma_mperr_intr, sc);
+       sc->sc_errint_ih = intr_establish(obio->obio_intrbase + 2,
+           IPL_SCHED, IST_LEVEL, edma_errint_intr, sc);



Home | Main Index | Thread Index | Old Index