svn commit: r261639 - in head/sys: arm/freescale/vybrid boot/fdt/dts

Ruslan Bukin br at FreeBSD.org
Sat Feb 8 19:48:00 UTC 2014


Author: br
Date: Sat Feb  8 19:47:59 2014
New Revision: 261639
URL: http://svnweb.freebsd.org/changeset/base/261639

Log:
  Add drivers for:
  - Enhanced Direct Memory Access Controller (eDMA)
  - Direct Memory Access Multiplexer (DMAMUX)

Added:
  head/sys/arm/freescale/vybrid/vf_dmamux.c   (contents, props changed)
  head/sys/arm/freescale/vybrid/vf_dmamux.h   (contents, props changed)
  head/sys/arm/freescale/vybrid/vf_edma.c   (contents, props changed)
  head/sys/arm/freescale/vybrid/vf_edma.h   (contents, props changed)
Modified:
  head/sys/arm/freescale/vybrid/files.vybrid
  head/sys/boot/fdt/dts/vybrid.dtsi

Modified: head/sys/arm/freescale/vybrid/files.vybrid
==============================================================================
--- head/sys/arm/freescale/vybrid/files.vybrid	Sat Feb  8 16:37:54 2014	(r261638)
+++ head/sys/arm/freescale/vybrid/files.vybrid	Sat Feb  8 19:47:59 2014	(r261639)
@@ -21,6 +21,8 @@ arm/freescale/vybrid/vf_anadig.c		standa
 arm/freescale/vybrid/vf_iomuxc.c		standard
 arm/freescale/vybrid/vf_mscm.c			standard
 arm/freescale/vybrid/vf_src.c			standard
+arm/freescale/vybrid/vf_edma.c			standard
+arm/freescale/vybrid/vf_dmamux.c		standard
 arm/freescale/vybrid/vf_tcon.c			optional	vt
 arm/freescale/vybrid/vf_dcu4.c			optional	vt
 arm/freescale/vybrid/vf_nfc.c			optional	nand

Added: head/sys/arm/freescale/vybrid/vf_dmamux.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_dmamux.c	Sat Feb  8 19:47:59 2014	(r261639)
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Vybrid Family Direct Memory Access Multiplexer (DMAMUX)
+ * Chapter 22, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+#include <arm/freescale/vybrid/vf_dmamux.h>
+
+#define	DMAMUX_CHCFG(n)		(0x1 * n)	/* Channels 0-15 Cfg Reg */
+#define	CHCFG_ENBL		(1 << 7)	/* Channel Enable */
+#define	CHCFG_TRIG		(1 << 6)	/* Channel Trigger Enable */
+#define	CHCFG_SOURCE_MASK	0x3f		/* Channel Source (Slot) */
+#define	CHCFG_SOURCE_SHIFT	0
+
+struct dmamux_softc {
+	struct resource		*res[4];
+	bus_space_tag_t		bst[4];
+	bus_space_handle_t	bsh[4];
+};
+
+struct dmamux_softc *dmamux_sc;
+
+static struct resource_spec dmamux_spec[] = {
+	{ SYS_RES_MEMORY,	0,	RF_ACTIVE }, /* DMAMUX0 */
+	{ SYS_RES_MEMORY,	1,	RF_ACTIVE }, /* DMAMUX1 */
+	{ SYS_RES_MEMORY,	2,	RF_ACTIVE }, /* DMAMUX2 */
+	{ SYS_RES_MEMORY,	3,	RF_ACTIVE }, /* DMAMUX3 */
+	{ -1, 0 }
+};
+
+static int
+dmamux_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "fsl,mvf600-dmamux"))
+		return (ENXIO);
+
+	device_set_desc(dev, "Vybrid Family Direct Memory Access Multiplexer");
+	return (BUS_PROBE_DEFAULT);
+}
+
+int
+dmamux_configure(int mux, int source, int channel, int enable)
+{
+	struct dmamux_softc *sc;
+	int reg;
+
+	sc = dmamux_sc;
+
+	MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), 0x0);
+
+	reg = 0;
+	if (enable)
+		reg |= (CHCFG_ENBL);
+
+	reg &= ~(CHCFG_SOURCE_MASK << CHCFG_SOURCE_SHIFT);
+	reg |= (source << CHCFG_SOURCE_SHIFT);
+
+	MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), reg);
+
+	return (0);
+}
+
+static int
+dmamux_attach(device_t dev)
+{
+	struct dmamux_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	if (bus_alloc_resources(dev, dmamux_spec, sc->res)) {
+		device_printf(dev, "could not allocate resources\n");
+		return (ENXIO);
+	}
+
+	/* Memory interface */
+	for (i = 0; i < 4; i++) {
+		sc->bst[i] = rman_get_bustag(sc->res[i]);
+		sc->bsh[i] = rman_get_bushandle(sc->res[i]);
+	}
+
+	dmamux_sc = sc;
+
+	return (0);
+}
+
+static device_method_t dmamux_methods[] = {
+	DEVMETHOD(device_probe,		dmamux_probe),
+	DEVMETHOD(device_attach,	dmamux_attach),
+	{ 0, 0 }
+};
+
+static driver_t dmamux_driver = {
+	"dmamux",
+	dmamux_methods,
+	sizeof(struct dmamux_softc),
+};
+
+static devclass_t dmamux_devclass;
+
+DRIVER_MODULE(dmamux, simplebus, dmamux_driver, dmamux_devclass, 0, 0);

Added: head/sys/arm/freescale/vybrid/vf_dmamux.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_dmamux.h	Sat Feb  8 19:47:59 2014	(r261639)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+int dmamux_configure(int mux, int source, int channel, int enable);
+
+enum mux_num {
+	MUX0,
+	MUX1,
+	MUX2,
+	MUX3,
+};
+
+enum mux_grp {
+	MUXGRP0, /* MUX[0,3] */
+	MUXGRP1, /* MUX[1,2] */
+};
+
+/* DMAMUX */
+#define	MUX_READ1(_sc, _mux, _reg)				\
+	bus_space_read_1(_sc->bst[_mux], _sc->bsh[_mux], _reg)
+
+#define	MUX_WRITE1(_sc, _mux, _reg, _val)			\
+	bus_space_write_1(_sc->bst[_mux], _sc->bsh[_mux], _reg, _val)

Added: head/sys/arm/freescale/vybrid/vf_edma.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_edma.c	Sat Feb  8 19:47:59 2014	(r261639)
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Vybrid Family Enhanced Direct Memory Access Controller (eDMA)
+ * Chapter 21, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_edma.h>
+#include <arm/freescale/vybrid/vf_dmamux.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+struct edma_channel {
+	uint32_t	enabled;
+	uint32_t	mux_num;
+	uint32_t	mux_src;
+	uint32_t	mux_chn;
+	uint32_t	(*ih) (void *, int);
+	void		*ih_user;
+};
+
+static struct edma_channel edma_map[EDMA_NUM_CHANNELS];
+
+static struct resource_spec edma_spec[] = {
+	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
+	{ SYS_RES_MEMORY,	1,	RF_ACTIVE }, /* TCD */
+	{ SYS_RES_IRQ,		0,	RF_ACTIVE }, /* Transfer complete */
+	{ SYS_RES_IRQ,		1,	RF_ACTIVE }, /* Error Interrupt */
+	{ -1, 0 }
+};
+
+static int
+edma_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "fsl,mvf600-edma"))
+		return (ENXIO);
+
+	device_set_desc(dev, "Vybrid Family eDMA Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static void
+edma_transfer_complete_intr(void *arg)
+{
+	struct edma_channel *ch;
+	struct edma_softc *sc;
+	int interrupts;
+	int i;
+
+	sc = arg;
+
+	interrupts = READ4(sc, DMA_INT);
+	WRITE1(sc, DMA_CINT, CINT_CAIR);
+
+	for (i = 0; i < EDMA_NUM_CHANNELS; i++) {
+		if (interrupts & (0x1 << i)) {
+			ch = &edma_map[i];
+			if (ch->enabled == 1) {
+				if (ch->ih != NULL) {
+					ch->ih(ch->ih_user, i);
+				}
+			}
+		}
+	}
+}
+
+static void
+edma_err_intr(void *arg)
+{
+	struct edma_softc *sc;
+	int reg;
+
+	sc = arg;
+
+	reg = READ4(sc, DMA_ERR);
+
+#if 0
+	device_printf(sc->dev, "DMA_ERR 0x%08x, ES 0x%08x\n",
+	    reg, READ4(sc, DMA_ES));
+#endif
+
+	WRITE1(sc, DMA_CERR, CERR_CAEI);
+}
+
+static int
+channel_free(struct edma_softc *sc, int chnum)
+{
+	struct edma_channel *ch;
+
+	ch = &edma_map[chnum];
+	ch->enabled = 0;
+
+	dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 0);
+
+	return (0);
+}
+
+static int
+channel_configure(struct edma_softc *sc, int mux_grp, int mux_src)
+{
+	struct edma_channel *ch;
+	int channel_first;
+	int mux_num;
+	int chnum;
+	int i;
+
+	if ((sc->device_id == 0 && mux_grp == 1) ||	\
+	    (sc->device_id == 1 && mux_grp == 0)) {
+		channel_first = NCHAN_PER_MUX;
+		mux_num = (sc->device_id * 2) + 1;
+	} else {
+		channel_first = 0;
+		mux_num = sc->device_id * 2;
+	};
+
+	/* Take first unused eDMA channel */
+	ch = NULL;
+	for (i = channel_first; i < (channel_first + NCHAN_PER_MUX); i++) {
+		ch = &edma_map[i];
+		if (ch->enabled == 0) {
+			break;
+		}
+		ch = NULL;
+	};
+
+	if (ch == NULL) {
+		/* Can't find free channel */
+		return (-1);
+	};
+
+	chnum = i;
+
+	ch->enabled = 1;
+	ch->mux_num = mux_num;
+	ch->mux_src = mux_src;
+	ch->mux_chn = (chnum - channel_first);	/* 0 to 15 */
+
+	dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 1);
+
+	return (chnum);
+}
+
+static int
+dma_stop(struct edma_softc *sc, int chnum)
+{
+	int reg;
+
+	reg = READ4(sc, DMA_ERQ);
+	reg &= ~(0x1 << chnum);
+	WRITE4(sc, DMA_ERQ, reg);
+
+	return (0);
+}
+
+static int
+dma_setup(struct edma_softc *sc, struct tcd_conf *tcd)
+{
+	struct edma_channel *ch;
+	int chnum;
+	int reg;
+
+	chnum = tcd->channel;
+
+	ch = &edma_map[chnum];
+	ch->ih = tcd->ih;
+	ch->ih_user = tcd->ih_user;
+
+	TCD_WRITE4(sc, DMA_TCDn_SADDR(chnum), tcd->saddr);
+	TCD_WRITE4(sc, DMA_TCDn_DADDR(chnum), tcd->daddr);
+
+	reg = (tcd->smod << TCD_ATTR_SMOD_SHIFT);
+	reg |= (tcd->dmod << TCD_ATTR_DMOD_SHIFT);
+	reg |= (tcd->ssize << TCD_ATTR_SSIZE_SHIFT);
+	reg |= (tcd->dsize << TCD_ATTR_DSIZE_SHIFT);
+	TCD_WRITE2(sc, DMA_TCDn_ATTR(chnum), reg);
+
+	TCD_WRITE2(sc, DMA_TCDn_SOFF(chnum), tcd->soff);
+	TCD_WRITE2(sc, DMA_TCDn_DOFF(chnum), tcd->doff);
+	TCD_WRITE4(sc, DMA_TCDn_SLAST(chnum), tcd->slast);
+	TCD_WRITE4(sc, DMA_TCDn_DLASTSGA(chnum), tcd->dlast_sga);
+	TCD_WRITE4(sc, DMA_TCDn_NBYTES_MLOFFYES(chnum), tcd->nbytes);
+
+	reg = tcd->nmajor; /* Current Major Iteration Count */
+	TCD_WRITE2(sc, DMA_TCDn_CITER_ELINKNO(chnum), reg);
+	TCD_WRITE2(sc, DMA_TCDn_BITER_ELINKNO(chnum), reg);
+
+	reg = (TCD_CSR_INTMAJOR);
+	if(tcd->majorelink == 1) {
+		reg |= TCD_CSR_MAJORELINK;
+		reg |= (tcd->majorelinkch << TCD_CSR_MAJORELINKCH_SHIFT);
+	}
+	TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
+
+	/* Enable requests */
+	reg = READ4(sc, DMA_ERQ);
+	reg |= (0x1 << chnum);
+	WRITE4(sc, DMA_ERQ, reg);
+
+	/* Enable error interrupts */
+	reg = READ4(sc, DMA_EEI);
+	reg |= (0x1 << chnum);
+	WRITE4(sc, DMA_EEI, reg);
+
+	return (0);
+}
+
+static int
+dma_request(struct edma_softc *sc, int chnum)
+{
+	int reg;
+
+	/* Start */
+	reg = TCD_READ2(sc, DMA_TCDn_CSR(chnum));
+	reg |= TCD_CSR_START;
+	TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
+
+	return (0);
+}
+
+static int
+edma_attach(device_t dev)
+{
+	struct edma_softc *sc;
+	phandle_t node;
+	int dts_value;
+	int len;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	if ((node = ofw_bus_get_node(sc->dev)) == -1)
+		return (ENXIO);
+
+	if ((len = OF_getproplen(node, "device-id")) <= 0)
+		return (ENXIO);
+
+	OF_getprop(node, "device-id", &dts_value, len);
+	sc->device_id = fdt32_to_cpu(dts_value);
+
+	sc->dma_stop = dma_stop;
+	sc->dma_setup = dma_setup;
+	sc->dma_request = dma_request;
+	sc->channel_configure = channel_configure;
+	sc->channel_free = channel_free;
+
+	if (bus_alloc_resources(dev, edma_spec, sc->res)) {
+		device_printf(dev, "could not allocate resources\n");
+		return (ENXIO);
+	}
+
+	/* Memory interface */
+	sc->bst = rman_get_bustag(sc->res[0]);
+	sc->bsh = rman_get_bushandle(sc->res[0]);
+	sc->bst_tcd = rman_get_bustag(sc->res[1]);
+	sc->bsh_tcd = rman_get_bushandle(sc->res[1]);
+
+	/* Setup interrupt handlers */
+	if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
+		NULL, edma_transfer_complete_intr, sc, &sc->tc_ih)) {
+		device_printf(dev, "Unable to alloc DMA intr resource.\n");
+		return (ENXIO);
+	}
+
+	if (bus_setup_intr(dev, sc->res[3], INTR_TYPE_BIO | INTR_MPSAFE,
+		NULL, edma_err_intr, sc, &sc->err_ih)) {
+		device_printf(dev, "Unable to alloc DMA Err intr resource.\n");
+		return (ENXIO);
+	}
+
+	return (0);
+}
+
+static device_method_t edma_methods[] = {
+	DEVMETHOD(device_probe,		edma_probe),
+	DEVMETHOD(device_attach,	edma_attach),
+	{ 0, 0 }
+};
+
+static driver_t edma_driver = {
+	"edma",
+	edma_methods,
+	sizeof(struct edma_softc),
+};
+
+static devclass_t edma_devclass;
+
+DRIVER_MODULE(edma, simplebus, edma_driver, edma_devclass, 0, 0);

Added: head/sys/arm/freescale/vybrid/vf_edma.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_edma.h	Sat Feb  8 19:47:59 2014	(r261639)
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#define	DMA_CR		0x000	/* Control */
+#define	DMA_ES		0x004	/* Error Status */
+#define	DMA_ERQ		0x00C	/* Enable Request */
+#define	DMA_EEI		0x014	/* Enable Error Interrupt */
+#define	DMA_CEEI	0x018	/* Clear Enable Error Interrupt */
+#define	DMA_SEEI	0x019	/* Set Enable Error Interrupt */
+#define	DMA_CERQ	0x01A	/* Clear Enable Request */
+#define	DMA_SERQ	0x01B	/* Set Enable Request */
+#define	DMA_CDNE	0x01C	/* Clear DONE Status Bit */
+#define	DMA_SSRT	0x01D	/* Set START Bit */
+#define	DMA_CERR	0x01E	/* Clear Error */
+#define	 CERR_CAEI	(1 << 6) /* Clear All Error Indicators */
+#define	DMA_CINT	0x01F	/* Clear Interrupt Request */
+#define	 CINT_CAIR	(1 << 6) /* Clear All Interrupt Requests */
+#define	DMA_INT		0x024	/* Interrupt Request */
+#define	DMA_ERR		0x02C	/* Error */
+#define	DMA_HRS		0x034	/* Hardware Request Status */
+#define	DMA_EARS	0x044	/* Enable Asynchronous Request in Stop */
+#define	DMA_DCHPRI3	0x100	/* Channel n Priority */
+#define	DMA_DCHPRI2	0x101	/* Channel n Priority */
+#define	DMA_DCHPRI1	0x102	/* Channel n Priority */
+#define	DMA_DCHPRI0	0x103	/* Channel n Priority */
+#define	DMA_DCHPRI7	0x104	/* Channel n Priority */
+#define	DMA_DCHPRI6	0x105	/* Channel n Priority */
+#define	DMA_DCHPRI5	0x106	/* Channel n Priority */
+#define	DMA_DCHPRI4	0x107	/* Channel n Priority */
+#define	DMA_DCHPRI11	0x108	/* Channel n Priority */
+#define	DMA_DCHPRI10	0x109	/* Channel n Priority */
+#define	DMA_DCHPRI9	0x10A	/* Channel n Priority */
+#define	DMA_DCHPRI8	0x10B	/* Channel n Priority */
+#define	DMA_DCHPRI15	0x10C	/* Channel n Priority */
+#define	DMA_DCHPRI14	0x10D	/* Channel n Priority */
+#define	DMA_DCHPRI13	0x10E	/* Channel n Priority */
+#define	DMA_DCHPRI12	0x10F	/* Channel n Priority */
+#define	DMA_DCHPRI19	0x110	/* Channel n Priority */
+#define	DMA_DCHPRI18	0x111	/* Channel n Priority */
+#define	DMA_DCHPRI17	0x112	/* Channel n Priority */
+#define	DMA_DCHPRI16	0x113	/* Channel n Priority */
+#define	DMA_DCHPRI23	0x114	/* Channel n Priority */
+#define	DMA_DCHPRI22	0x115	/* Channel n Priority */
+#define	DMA_DCHPRI21	0x116	/* Channel n Priority */
+#define	DMA_DCHPRI20	0x117	/* Channel n Priority */
+#define	DMA_DCHPRI27	0x118	/* Channel n Priority */
+#define	DMA_DCHPRI26	0x119	/* Channel n Priority */
+#define	DMA_DCHPRI25	0x11A	/* Channel n Priority */
+#define	DMA_DCHPRI24	0x11B	/* Channel n Priority */
+#define	DMA_DCHPRI31	0x11C	/* Channel n Priority */
+#define	DMA_DCHPRI30	0x11D	/* Channel n Priority */
+#define	DMA_DCHPRI29	0x11E	/* Channel n Priority */
+#define	DMA_DCHPRI28	0x11F	/* Channel n Priority */
+
+#define	DMA_TCDn_SADDR(n)		(0x00 + 0x20 * n)	/* Source Address */
+#define	DMA_TCDn_SOFF(n)		(0x04 + 0x20 * n)	/* Signed Source Address Offset */
+#define	DMA_TCDn_ATTR(n)		(0x06 + 0x20 * n)	/* Transfer Attributes */
+#define	DMA_TCDn_NBYTES_MLNO(n)		(0x08 + 0x20 * n)	/* Minor Byte Count */
+#define	DMA_TCDn_NBYTES_MLOFFNO(n)	(0x08 + 0x20 * n)	/* Signed Minor Loop Offset */
+#define	DMA_TCDn_NBYTES_MLOFFYES(n)	(0x08 + 0x20 * n)	/* Signed Minor Loop Offset */
+#define	DMA_TCDn_SLAST(n)		(0x0C + 0x20 * n)	/* Last Source Address Adjustment */
+#define	DMA_TCDn_DADDR(n)		(0x10 + 0x20 * n)	/* Destination Address */
+#define	DMA_TCDn_DOFF(n)		(0x14 + 0x20 * n)	/* Signed Destination Address Offset */
+#define	DMA_TCDn_CITER_ELINKYES(n)	(0x16 + 0x20 * n)	/* Current Minor Loop Link, Major Loop Count */
+#define	DMA_TCDn_CITER_ELINKNO(n)	(0x16 + 0x20 * n)
+#define	DMA_TCDn_DLASTSGA(n)		(0x18 + 0x20 * n)	/* Last Dst Addr Adjustment/Scatter Gather Address */
+#define	DMA_TCDn_CSR(n)			(0x1C + 0x20 * n)	/* Control and Status */
+#define	DMA_TCDn_BITER_ELINKYES(n)	(0x1E + 0x20 * n)	/* Beginning Minor Loop Link, Major Loop Count */
+#define	DMA_TCDn_BITER_ELINKNO(n)	(0x1E + 0x20 * n)	/* Beginning Minor Loop Link, Major Loop Count */
+
+#define TCD_CSR_START			(1 << 0)
+#define	TCD_CSR_INTMAJOR		(1 << 1)
+#define	TCD_CSR_INTHALF			(1 << 2)
+#define	TCD_CSR_DREQ			(1 << 3)
+#define	TCD_CSR_ESG			(1 << 4)
+#define	TCD_CSR_MAJORELINK		(1 << 5)
+#define	TCD_CSR_ACTIVE			(1 << 6)
+#define	TCD_CSR_DONE			(1 << 7)
+#define	TCD_CSR_MAJORELINKCH_SHIFT	8
+
+#define	TCD_ATTR_SMOD_SHIFT		11	/* Source Address Modulo */
+#define	TCD_ATTR_SSIZE_SHIFT		8	/* Source Data Transfer Size */
+#define	TCD_ATTR_DMOD_SHIFT		3	/* Dst Address Modulo */
+#define	TCD_ATTR_DSIZE_SHIFT		0	/* Dst Data Transfer Size */
+
+#define	TCD_READ4(_sc, _reg)		\
+	bus_space_read_4(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define	TCD_WRITE4(_sc, _reg, _val)	\
+	bus_space_write_4(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+#define	TCD_READ2(_sc, _reg)		\
+	bus_space_read_2(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define	TCD_WRITE2(_sc, _reg, _val)	\
+	bus_space_write_2(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+#define	TCD_READ1(_sc, _reg)		\
+	bus_space_read_1(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define	TCD_WRITE1(_sc, _reg, _val)	\
+	bus_space_write_1(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+
+#define	EDMA_NUM_DEVICES	2
+#define	EDMA_NUM_CHANNELS	32
+#define	NCHAN_PER_MUX		16
+
+struct tcd_conf {
+	bus_addr_t	saddr;
+	bus_addr_t	daddr;
+	uint32_t	nbytes;
+	uint32_t	nmajor;
+	uint32_t	majorelink;
+	uint32_t	majorelinkch;
+	uint32_t	esg;
+	uint32_t	smod;
+	uint32_t	dmod;
+	uint32_t	soff;
+	uint32_t	doff;
+	uint32_t	ssize;
+	uint32_t	dsize;
+	uint32_t	slast;
+	uint32_t	dlast_sga;
+	uint32_t	channel;
+	uint32_t	(*ih)(void *, int);
+	void		*ih_user;
+};
+
+/*
+ * TCD struct is described at
+ * Vybrid Reference Manual, Rev. 5, 07/2013
+ *
+ * Should be used for Scatter/Gathering feature.
+ */
+
+struct TCD {
+	uint32_t	saddr;
+	uint16_t	attr;
+	uint16_t	soff;
+	uint32_t	nbytes;
+	uint32_t	slast;
+	uint32_t	daddr;
+	uint16_t	citer;
+	uint16_t	doff;
+	uint32_t	dlast_sga;
+	uint16_t	biter;
+	uint16_t	csr;
+} __packed;
+
+struct edma_softc {
+	device_t		dev;
+	struct resource		*res[4];
+	bus_space_tag_t		bst;
+	bus_space_handle_t	bsh;
+	bus_space_tag_t		bst_tcd;
+	bus_space_handle_t	bsh_tcd;
+	void			*tc_ih;
+	void			*err_ih;
+	uint32_t		device_id;
+
+	int	(*channel_configure) (struct edma_softc *, int, int);
+	int	(*channel_free) (struct edma_softc *, int);
+	int	(*dma_request) (struct edma_softc *, int);
+	int	(*dma_setup) (struct edma_softc *, struct tcd_conf *);
+	int	(*dma_stop) (struct edma_softc *, int);
+};

Modified: head/sys/boot/fdt/dts/vybrid.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/vybrid.dtsi	Sat Feb  8 16:37:54 2014	(r261638)
+++ head/sys/boot/fdt/dts/vybrid.dtsi	Sat Feb  8 19:47:59 2014	(r261639)
@@ -111,6 +111,7 @@
 			      <0x40019000 0x1000>; /* TCD */
 			interrupts = < 40 41 >;
 			interrupt-parent = <&GIC>;
+			device-id = < 0 >;
 			status = "disabled";
 		};
 
@@ -120,6 +121,7 @@
 			      <0x40099000 0x1000>; /* TCD */
 			interrupts = < 42 43 >;
 			interrupt-parent = <&GIC>;
+			device-id = < 1 >;
 			status = "disabled";
 		};
 
@@ -308,6 +310,7 @@
 			interrupts = < 119 >;
 			interrupt-parent = <&GIC>;
 			status = "disabled";
+			edma-controller = <&edma1>;
 			clock_names = "sai3", "cko1";
 			iomux_config = < 16 0x2
 					 19 0x2


More information about the svn-src-all mailing list