summaryrefslogtreecommitdiffstats
path: root/sys/arm/freescale
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-15 18:38:19 +0000
committerian <ian@FreeBSD.org>2014-05-15 18:38:19 +0000
commitc287c5d5301219fe2fabc25222edae29e314c213 (patch)
tree6279c6bac201dbed9f74b5d6ff7052423f603994 /sys/arm/freescale
parentaa8cf0356302220da5d26bb149e6a0f5061fae7b (diff)
downloadFreeBSD-src-c287c5d5301219fe2fabc25222edae29e314c213.zip
FreeBSD-src-c287c5d5301219fe2fabc25222edae29e314c213.tar.gz
MFC r261616, r261639
Remove FreeBSD 6 support from atmel usb controllers. Add Vybrid drivers for: - Enhanced Direct Memory Access Controller (eDMA) - Direct Memory Access Multiplexer (DMAMUX)
Diffstat (limited to 'sys/arm/freescale')
-rw-r--r--sys/arm/freescale/vybrid/files.vybrid2
-rw-r--r--sys/arm/freescale/vybrid/vf_dmamux.c155
-rw-r--r--sys/arm/freescale/vybrid/vf_dmamux.h48
-rw-r--r--sys/arm/freescale/vybrid/vf_edma.c338
-rw-r--r--sys/arm/freescale/vybrid/vf_edma.h186
5 files changed, 729 insertions, 0 deletions
diff --git a/sys/arm/freescale/vybrid/files.vybrid b/sys/arm/freescale/vybrid/files.vybrid
index 6b77ff2..756beb9 100644
--- a/sys/arm/freescale/vybrid/files.vybrid
+++ b/sys/arm/freescale/vybrid/files.vybrid
@@ -21,6 +21,8 @@ arm/freescale/vybrid/vf_anadig.c standard
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
diff --git a/sys/arm/freescale/vybrid/vf_dmamux.c b/sys/arm/freescale/vybrid/vf_dmamux.c
new file mode 100644
index 0000000..1909621
--- /dev/null
+++ b/sys/arm/freescale/vybrid/vf_dmamux.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@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);
diff --git a/sys/arm/freescale/vybrid/vf_dmamux.h b/sys/arm/freescale/vybrid/vf_dmamux.h
new file mode 100644
index 0000000..92fa076
--- /dev/null
+++ b/sys/arm/freescale/vybrid/vf_dmamux.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@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)
diff --git a/sys/arm/freescale/vybrid/vf_edma.c b/sys/arm/freescale/vybrid/vf_edma.c
new file mode 100644
index 0000000..c5df919
--- /dev/null
+++ b/sys/arm/freescale/vybrid/vf_edma.c
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@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);
diff --git a/sys/arm/freescale/vybrid/vf_edma.h b/sys/arm/freescale/vybrid/vf_edma.h
new file mode 100644
index 0000000..5f77eacc
--- /dev/null
+++ b/sys/arm/freescale/vybrid/vf_edma.h
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@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);
+};
OpenPOWER on IntegriCloud