Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Apr 2012 15:43:32 +0000 (UTC)
From:      Damjan Marion <dmarion@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r234344 - in projects/armv6/sys: arm/ti arm/ti/am335x boot/fdt/dts
Message-ID:  <201204161543.q3GFhWZ8039848@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dmarion
Date: Mon Apr 16 15:43:31 2012
New Revision: 234344
URL: http://svn.freebsd.org/changeset/base/234344

Log:
  TI EDMA3 driver and modifications of TI MMC driver to
  use this DMA controller in addition to existing sDMA.
  
  This brings MMC/SD card access to AM335x/beaglebone.
  ti_mmchs requires additional cleanup.

Added:
  projects/armv6/sys/arm/ti/ti_edma3.c
  projects/armv6/sys/arm/ti/ti_edma3.h
Modified:
  projects/armv6/sys/arm/ti/am335x/files.am335x
  projects/armv6/sys/arm/ti/ti_mmchs.c
  projects/armv6/sys/arm/ti/ti_mmchs.h
  projects/armv6/sys/boot/fdt/dts/beaglebone.dts

Modified: projects/armv6/sys/arm/ti/am335x/files.am335x
==============================================================================
--- projects/armv6/sys/arm/ti/am335x/files.am335x	Mon Apr 16 15:08:01 2012	(r234343)
+++ projects/armv6/sys/arm/ti/am335x/files.am335x	Mon Apr 16 15:43:31 2012	(r234344)
@@ -4,5 +4,6 @@ arm/ti/aintc.c				standard
 arm/ti/am335x/am335x_prcm.c		standard
 arm/ti/am335x/am335x_dmtimer.c		standard
 arm/ti/am335x/am335x_scm_padconf.c	standard
-
+arm/ti/ti_edma3.c			standard
+arm/ti/ti_mmchs.c			optional	mmc
 arm/ti/cpsw/if_cpsw.c			optional	cpsw

Added: projects/armv6/sys/arm/ti/ti_edma3.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/armv6/sys/arm/ti/ti_edma3.c	Mon Apr 16 15:43:31 2012	(r234344)
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ * 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.
+ * 3. Neither the name of authors nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <sys/sockio.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/ti_prcm.h>
+
+#include <arm/ti/ti_edma3.h>
+
+#define TI_EDMA3_NUM_TCS		3
+#define TI_EDMA3_NUM_IRQS		3
+#define TI_EDMA3_NUM_DMA_CHS		64
+#define TI_EDMA3_NUM_QDMA_CHS		8
+
+#define TI_EDMA3CC_PID			0x000
+#define TI_EDMA3CC_DCHMAP(p)		(0x100 + ((p)*4))
+#define TI_EDMA3CC_DMAQNUM(n)		(0x240 + ((n)*4))
+#define TI_EDMA3CC_QDMAQNUM		0x260
+#define TI_EDMA3CC_EMCR			0x308
+#define TI_EDMA3CC_EMCRH		0x30C
+#define TI_EDMA3CC_QEMCR		0x314
+#define TI_EDMA3CC_CCERR		0x318
+#define TI_EDMA3CC_CCERRCLR		0x31C
+#define TI_EDMA3CC_DRAE(p)		(0x340 + ((p)*8))
+#define TI_EDMA3CC_DRAEH(p)		(0x344 + ((p)*8))
+#define TI_EDMA3CC_QRAE(p)		(0x380 + ((p)*4))
+#define TI_EDMA3CC_S_ESR(p)		(0x2010 + ((p)*0x200))
+#define TI_EDMA3CC_S_ESRH(p)		(0x2014 + ((p)*0x200))
+#define TI_EDMA3CC_S_SECR(p)		(0x2040 + ((p)*0x200))
+#define TI_EDMA3CC_S_SECRH(p)		(0x2044 + ((p)*0x200))
+#define TI_EDMA3CC_S_EESR(p)		(0x2030 + ((p)*0x200))
+#define TI_EDMA3CC_S_EESRH(p)		(0x2034 + ((p)*0x200))
+#define TI_EDMA3CC_S_IESR(p)		(0x2060 + ((p)*0x200))
+#define TI_EDMA3CC_S_IESRH(p)		(0x2064 + ((p)*0x200))
+#define TI_EDMA3CC_S_IPR(p)		(0x2068 + ((p)*0x200))
+#define TI_EDMA3CC_S_IPRH(p)		(0x206C + ((p)*0x200))
+#define TI_EDMA3CC_S_QEESR(p)		(0x208C + ((p)*0x200))
+
+#define TI_EDMA3CC_PARAM_OFFSET		0x4000
+#define TI_EDMA3CC_OPT(p)		(TI_EDMA3CC_PARAM_OFFSET + 0x0 + ((p)*0x20))
+
+#define TI_EDMA3CC_DMAQNUM_SET(c,q)	((0x7 & (q)) << (((c) % 8) * 4))
+#define TI_EDMA3CC_DMAQNUM_CLR(c)	(~(0x7 << (((c) % 8) * 4)))
+#define TI_EDMA3CC_QDMAQNUM_SET(c,q)	((0x7 & (q)) << ((c) * 4))
+#define TI_EDMA3CC_QDMAQNUM_CLR(c)	(~(0x7 << ((c) * 4)))
+
+#define TI_EDMA3CC_OPT_TCC_CLR		(~(0x3F000))
+#define TI_EDMA3CC_OPT_TCC_SET(p)	(((0x3F000 >> 12) & (p)) << 12)
+
+struct ti_edma3_softc {
+	device_t		sc_dev;
+	struct resource *	mem_res[TI_EDMA3_NUM_TCS+1];
+	struct resource *	irq_res[TI_EDMA3_NUM_IRQS];
+	void			*ih_cookie[TI_EDMA3_NUM_IRQS];
+};
+
+static struct ti_edma3_softc *ti_edma3_sc = NULL;
+
+static struct resource_spec ti_edma3_mem_spec[] = {
+	{ SYS_RES_MEMORY,   0,  RF_ACTIVE },
+	{ SYS_RES_MEMORY,   1,  RF_ACTIVE },
+	{ SYS_RES_MEMORY,   2,  RF_ACTIVE },
+	{ SYS_RES_MEMORY,   3,  RF_ACTIVE },
+	{ -1,               0,  0 }
+};
+static struct resource_spec ti_edma3_irq_spec[] = {
+	{ SYS_RES_IRQ,      0,  RF_ACTIVE },
+	{ SYS_RES_IRQ,      1,  RF_ACTIVE },
+	{ SYS_RES_IRQ,      2,  RF_ACTIVE },
+	{ -1,               0,  0 }
+};
+
+/* Read/Write macros */
+#define ti_edma3_cc_rd_4(reg)		bus_read_4(ti_edma3_sc->mem_res[0], reg)
+#define ti_edma3_cc_wr_4(reg, val)	bus_write_4(ti_edma3_sc->mem_res[0], reg, val)
+#define ti_edma3_tc_rd_4(c, reg)	bus_read_4(ti_edma3_sc->mem_res[c+1], reg)
+#define ti_edma3_tc_wr_4(c, reg, val)	bus_write_4(ti_edma3_sc->mem_res[c+1], reg, val)
+
+static void ti_edma3_intr_comp(void *arg);
+static void ti_edma3_intr_mperr(void *arg);
+static void ti_edma3_intr_err(void *arg);
+static int ti_edma3_enable_event_intr(unsigned int ch);
+
+static struct {
+	driver_intr_t *handler;
+	char * description;
+} ti_edma3_intrs[TI_EDMA3_NUM_IRQS] = {
+	{ ti_edma3_intr_comp,	"EDMA Completion Interrupt" },
+	{ ti_edma3_intr_mperr,	"EDMA Memory Protection Error Interrupt" },
+	{ ti_edma3_intr_err,	"EDMA Error Interrupt" },
+};
+
+static int
+ti_edma3_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "ti,edma"))
+		return (ENXIO);
+
+	device_set_desc(dev, "TI EDMA Controller");
+	return (0);
+}
+
+static int
+ti_edma3_attach(device_t dev)
+{
+	struct ti_edma3_softc *sc = device_get_softc(dev);
+	uint32_t reg;
+	int err;
+	int i;
+
+	if (ti_edma3_sc)
+		return (ENXIO);
+
+	ti_edma3_sc = sc;
+	sc->sc_dev = dev;
+
+	/* Request the memory resources */
+	err = bus_alloc_resources(dev, ti_edma3_mem_spec, sc->mem_res);
+	if (err) {
+		device_printf(dev, "Error: could not allocate mem resources\n");
+		return (ENXIO);
+	}
+
+	/* Request the IRQ resources */
+	err = bus_alloc_resources(dev, ti_edma3_irq_spec, sc->irq_res);
+	if (err) {
+		device_printf(dev, "Error: could not allocate irq resources\n");
+		return (ENXIO);
+	}
+
+	/* Enable Channel Controller */
+	ti_prcm_clk_enable(EDMA_TPCC_CLK);
+
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID);
+
+	device_printf(dev, "EDMA revision %08x\n", reg);
+
+
+	/* Attach interrupt handlers */
+	for (i = 0; i < TI_EDMA3_NUM_IRQS; ++i) {
+		err = bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC |
+		    INTR_MPSAFE, NULL, *ti_edma3_intrs[i].handler,
+		    sc, &sc->ih_cookie[i]);
+		if (err) {
+			device_printf(dev, "could not setup %s\n",
+			    ti_edma3_intrs[i].description);
+			return (err);
+		}
+	}
+
+	return (0);
+}
+
+static device_method_t ti_edma3_methods[] = {
+	DEVMETHOD(device_probe, ti_edma3_probe),
+	DEVMETHOD(device_attach, ti_edma3_attach),
+	{0, 0},
+};
+
+static driver_t ti_edma3_driver = {
+	"ti_edma3",
+	ti_edma3_methods,
+	sizeof(struct ti_edma3_softc),
+};
+static devclass_t ti_edma3_devclass;
+
+DRIVER_MODULE(ti_edma3, simplebus, ti_edma3_driver, ti_edma3_devclass, 0, 0);
+MODULE_DEPEND(ti_edma3, ti_prcm, 1, 1, 1);
+
+static void
+ti_edma3_intr_comp(void *arg)
+{
+	printf("%s: unimplemented\n", __func__);
+}
+
+static void
+ti_edma3_intr_mperr(void *arg)
+{
+	printf("%s: unimplemented\n", __func__);
+}
+
+static void
+ti_edma3_intr_err(void *arg)
+{
+	printf("%s: unimplemented\n", __func__);
+}
+
+void
+ti_edma3_init(unsigned int eqn)
+{
+	uint32_t reg;
+	int i;
+
+	/* on AM335x Event queue 0 is always mapped to Transfer Controller 0,
+	 * event queue 1 to TC2, etc. So we are asking PRCM to power on specific
+	 * TC based on what event queue we need to initialize */
+	ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn);
+
+	/* Clear Event Missed Regs */
+	ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 0xFFFFFFFF);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_QEMCR, 0xFFFFFFFF);
+
+	/* Clear Error Reg */
+	ti_edma3_cc_wr_4(TI_EDMA3CC_CCERRCLR, 0xFFFFFFFF);
+
+	/* Enable DMA channels 0-63 */
+	ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), 0xFFFFFFFF);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), 0xFFFFFFFF);
+
+	for (i = 0; i < 64; i++) {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_DCHMAP(i), i<<5);
+	}
+
+	/* Initialize the DMA Queue Number Registers */
+	for (i = 0; i < TI_EDMA3_NUM_DMA_CHS; i++) {
+		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(i>>3));
+		reg &= TI_EDMA3CC_DMAQNUM_CLR(i);
+		reg |= TI_EDMA3CC_DMAQNUM_SET(i, eqn);
+		ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(i>>3), reg);
+	}
+
+	/* Enable the QDMA Region access for all channels */
+	ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), (1 << TI_EDMA3_NUM_QDMA_CHS) - 1);
+
+	/*Initialize QDMA Queue Number Registers */
+	for (i = 0; i < TI_EDMA3_NUM_QDMA_CHS; i++) {
+		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
+		reg &= TI_EDMA3CC_QDMAQNUM_CLR(i);
+		reg |= TI_EDMA3CC_QDMAQNUM_SET(i, eqn);
+		ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
+	}
+}
+
+#ifdef notyet
+int
+ti_edma3_enable_event_intr(unsigned int ch)
+{
+	uint32_t reg;
+
+	if (ch >= TI_EDMA3_NUM_DMA_CHS)
+		return (-EINVAL);
+
+	if (ch < 32) {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESR(0), 1 << ch);
+	} else {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESRH(0), 1 << (ch - 32));
+	}
+	return 0;
+}
+#endif
+
+int
+ti_edma3_request_dma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
+{
+	uint32_t reg;
+
+	if (ch >= TI_EDMA3_NUM_DMA_CHS)
+		return (-EINVAL);
+
+	/* Enable the DMA channel in the DRAE/DRAEH registers */
+	if (ch < 32) {
+		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAE(0));
+		reg |= (0x01 << ch);
+		ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), reg);
+	} else {
+		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAEH(0));
+		reg |= (0x01 << (ch - 32));
+		ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), reg);
+	}
+
+	/* Associate DMA Channel to Event Queue */
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(ch >> 3));
+	reg &= TI_EDMA3CC_DMAQNUM_CLR(ch);
+	reg |= TI_EDMA3CC_DMAQNUM_SET((ch), eqn);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(ch >> 3), reg);
+
+	/* Set TCC in corresponding PaRAM Entry */
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
+	reg &= TI_EDMA3CC_OPT_TCC_CLR;
+	reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
+
+	return 0;
+}
+
+int
+ti_edma3_request_qdma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
+{
+	uint32_t reg;
+
+	if (ch >= TI_EDMA3_NUM_DMA_CHS)
+		return (-EINVAL);
+
+	/* Enable the QDMA channel in the QRAE registers */
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QRAE(0));
+	reg |= (0x01 << ch);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), reg);
+
+	/* Associate QDMA Channel to Event Queue */
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
+	reg |= TI_EDMA3CC_QDMAQNUM_SET(ch, eqn);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
+
+	/* Set TCC in corresponding PaRAM Entry */
+	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
+	reg &= TI_EDMA3CC_OPT_TCC_CLR;
+	reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
+	ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
+
+	return 0;
+}
+
+int
+ti_edma3_enable_transfer_manual(unsigned int ch)
+{
+	if (ch >= TI_EDMA3_NUM_DMA_CHS)
+		return (-EINVAL);
+
+	/* set corresponding bit in ESR/ESRH to set a event */
+	if (ch < 32) {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESR(0), 1 <<  ch);
+	} else {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESRH(0), 1 <<  (ch - 32));
+	}
+
+	return 0;
+}
+
+int
+ti_edma3_enable_transfer_qdma(unsigned int ch)
+{
+	if (ch >= TI_EDMA3_NUM_QDMA_CHS)
+		return (-EINVAL);
+
+	/* set corresponding bit in QEESR to enable QDMA event */
+	ti_edma3_cc_wr_4(TI_EDMA3CC_S_QEESR(0), (1 << ch));
+
+	return 0;
+}
+
+int
+ti_edma3_enable_transfer_event(unsigned int ch)
+{
+	if (ch >= TI_EDMA3_NUM_DMA_CHS)
+		return (-EINVAL);
+
+	/* Clear SECR(H) & EMCR(H) to clean any previous NULL request
+	 * and set corresponding bit in EESR to enable DMA event */
+	if(ch < 32) {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECR(0), (1 << ch));
+		ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, (1 << ch));
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESR(0), (1 << ch));
+	} else {
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECRH(0), 1 << (ch - 32));
+		ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 1 << (ch - 32));
+		ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESRH(0), 1 << (ch - 32));
+	}
+
+	return 0;
+}
+
+void
+ti_edma3_param_write(unsigned int ch, struct ti_edma3cc_param_set *prs)
+{
+	bus_write_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
+	    (uint32_t *) prs, 8);
+}
+
+void
+ti_edma3_param_read(unsigned int ch, struct ti_edma3cc_param_set *prs)
+{
+	bus_read_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
+	    (uint32_t *) prs, 8);
+}

Added: projects/armv6/sys/arm/ti/ti_edma3.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/armv6/sys/arm/ti/ti_edma3.h	Mon Apr 16 15:43:31 2012	(r234344)
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ * 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.
+ */
+
+#ifndef _TI_EDMA3_H_
+#define _TI_EDMA3_H_
+
+/* Direct Mapped EDMA3 Events */
+#define TI_EDMA3_EVENT_SDTXEVT1			2
+#define TI_EDMA3_EVENT_SDRXEVT1			3
+#define TI_EDMA3_EVENT_SDTXEVT0			24
+#define TI_EDMA3_EVENT_SDRXEVT0			25
+
+struct ti_edma3cc_param_set {
+	struct {
+		uint32_t sam:1;		/* Source address mode */
+		uint32_t dam:1;		/* Destination address mode */
+		uint32_t syncdim:1;	/* Transfer synchronization dimension */
+		uint32_t static_set:1;	/* Static Set */
+		uint32_t :4;
+		uint32_t fwid:3;	/* FIFO Width */
+		uint32_t tccmode:1;	/* Transfer complete code mode */
+		uint32_t tcc:6;		/* Transfer complete code */
+		uint32_t :2;
+		uint32_t tcinten:1;	/* Transfer complete interrupt enable */
+		uint32_t itcinten:1;	/* Intermediate xfer completion intr. ena */
+		uint32_t tcchen:1;	/* Transfer complete chaining enable */
+		uint32_t itcchen:1;	/* Intermediate xfer completion chaining ena */
+		uint32_t privid:4;	/* Privilege identification */
+		uint32_t :3;
+		uint32_t priv:1;	/* Privilege level */
+	} opt;
+	uint32_t src;			/* Channel Source Address */
+	uint16_t acnt;			/* Count for 1st Dimension */
+	uint16_t bcnt;			/* Count for 2nd Dimension */
+	uint32_t dst;			/* Channel Destination Address */
+	int16_t srcbidx;		/* Source B Index */
+	int16_t dstbidx;		/* Destination B Index */
+	uint16_t link;			/* Link Address */
+	uint16_t bcntrld;		/* BCNT Reload */
+	int16_t srccidx;		/* Source C Index */
+	int16_t dstcidx;		/* Destination C Index */
+	uint16_t ccnt;			/* Count for 3rd Dimension */
+	uint16_t reserved;		/* Reserved */
+};
+
+void ti_edma3_init(unsigned int eqn);
+int ti_edma3_request_dma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn);
+int ti_edma3_request_qdma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn);
+int ti_edma3_enable_transfer_manual(unsigned int ch);
+int ti_edma3_enable_transfer_qdma(unsigned int ch);
+int ti_edma3_enable_transfer_event(unsigned int ch);
+
+void ti_edma3_param_write(unsigned int ch, struct ti_edma3cc_param_set *prs);
+void ti_edma3_param_read(unsigned int ch, struct ti_edma3cc_param_set *prs);
+
+#endif /* _TI_EDMA3_H_ */

Modified: projects/armv6/sys/arm/ti/ti_mmchs.c
==============================================================================
--- projects/armv6/sys/arm/ti/ti_mmchs.c	Mon Apr 16 15:08:01 2012	(r234343)
+++ projects/armv6/sys/arm/ti/ti_mmchs.c	Mon Apr 16 15:43:31 2012	(r234344)
@@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$");
 #include "mmcbus_if.h"
 
 #include <arm/ti/ti_sdma.h>
+#include <arm/ti/ti_edma3.h>
 #include <arm/ti/ti_mmchs.h>
 #include <arm/ti/ti_cpuid.h>
 #include <arm/ti/ti_prcm.h>
@@ -114,6 +115,8 @@ struct ti_mmchs_softc {
 
 	unsigned int		sc_dmach_rd;
 	unsigned int		sc_dmach_wr;
+	int			dma_rx_trig;
+	int			dma_tx_trig;
 
 	device_t		sc_gpio_dev;
 	int			sc_wp_gpio_pin;  /* GPIO pin for MMC write protect */
@@ -250,6 +253,7 @@ ti_mmchs_getaddr(void *arg, bus_dma_segm
 	*(bus_addr_t *)arg = segs[0].ds_addr;
 }
 
+#ifndef SOC_TI_AM335X
 /**
  *	ti_mmchs_dma_intr - interrupt handler for DMA events triggered by the controller
  *	@ch: the dma channel number
@@ -268,6 +272,7 @@ ti_mmchs_dma_intr(unsigned int ch, uint3
 	 * interrupt from the MMC controller.
 	 */
 }
+#endif
 
 /**
  *	ti_mmchs_intr_xfer_compl - called if a 'transfer complete' IRQ was received
@@ -390,9 +395,17 @@ ti_mmchs_intr_error(struct ti_mmchs_soft
 
 		/* Abort the DMA transfer (DDIR bit tells direction) */
 		if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DDIR)
+#ifdef SOC_TI_AM335X
+			printf("%s: DMA unimplemented\n", __func__);
+#else
 			ti_sdma_stop_xfer(sc->sc_dmach_rd);
+#endif
 		else
+#ifdef SOC_TI_AM335X
+			printf("%s: DMA unimplemented\n", __func__);
+#else
 			ti_sdma_stop_xfer(sc->sc_dmach_wr);
+#endif
 
 		/* If an error occure abort the DMA operation and free the dma map */
 		if ((sc->sc_dmamapped > 0) && (cmd->error != MMC_ERR_NONE)) {
@@ -437,8 +450,8 @@ ti_mmchs_intr(void *arg)
 
 	TI_MMCHS_LOCK(sc);
 
-	stat_reg = ti_mmchs_read_4(sc, MMCHS_STAT)
-	    & (ti_mmchs_read_4(sc, MMCHS_IE) | MMCHS_STAT_ERRI);
+	stat_reg = ti_mmchs_read_4(sc, MMCHS_STAT) & (ti_mmchs_read_4(sc,
+	    MMCHS_IE) | MMCHS_STAT_ERRI);
 
 	if (sc->curcmd == NULL) {
 		device_printf(sc->sc_dev, "Error: current cmd NULL, already done?\n");
@@ -486,6 +499,58 @@ ti_mmchs_intr(void *arg)
 	TI_MMCHS_UNLOCK(sc);
 }
 
+#ifdef SOC_TI_AM335X
+static void
+ti_mmchs_edma3_rx_xfer_setup(struct ti_mmchs_softc *sc, uint32_t src_paddr,
+    uint32_t dst_paddr, uint16_t blk_size, uint16_t num_blks)
+{
+	struct ti_edma3cc_param_set ps;
+
+	bzero(&ps, sizeof(struct ti_edma3cc_param_set));
+	ps.src		= src_paddr;
+	ps.dst		= dst_paddr;
+	ps.dstbidx	= 4;
+	ps.dstcidx	= blk_size;
+	ps.acnt		= 4;
+	ps.bcnt		= blk_size/4;
+	ps.ccnt		= num_blks;
+	ps.link		= 0xffff;
+	ps.opt.tcc	= sc->dma_rx_trig;
+	ps.opt.tcinten	= 1;
+	ps.opt.fwid	= 2; /* fifo width is 32 */
+	ps.opt.sam	= 1;
+	ps.opt.syncdim	= 1;
+
+	ti_edma3_param_write(sc->dma_rx_trig, &ps);
+	ti_edma3_enable_transfer_event(sc->dma_rx_trig);
+}
+
+static void
+ti_mmchs_edma3_tx_xfer_setup(struct ti_mmchs_softc *sc, uint32_t src_paddr,
+    uint32_t dst_paddr, uint16_t blk_size, uint16_t num_blks)
+{
+	struct ti_edma3cc_param_set ps;
+
+	bzero(&ps, sizeof(struct ti_edma3cc_param_set));
+	ps.src		= src_paddr;
+	ps.dst		= dst_paddr;
+	ps.srccidx	= blk_size;
+	ps.bcnt		= blk_size/4;
+	ps.ccnt		= num_blks;
+	ps.srcbidx	= 4;
+	ps.acnt		= 0x4;
+	ps.link		= 0xffff;
+	ps.opt.tcc	= sc->dma_tx_trig;
+	ps.opt.tcinten	= 1;
+	ps.opt.fwid	= 2; /* fifo width is 32 */
+	ps.opt.dam	= 1;
+	ps.opt.syncdim	= 1;
+
+	ti_edma3_param_write(sc->dma_tx_trig, &ps);
+	ti_edma3_enable_transfer_event(sc->dma_tx_trig);
+}
+#endif
+
 /**
  *	ti_mmchs_start_cmd - starts the given command
  *	@sc: pointer to the driver context
@@ -510,8 +575,9 @@ ti_mmchs_start_cmd(struct ti_mmchs_softc
 	struct mmc_request *req;
 	void *vaddr;
 	bus_addr_t paddr;
+#ifndef SOC_TI_AM335X
 	uint32_t pktsize;
-
+#endif
 	sc->curcmd = cmd;
 	data = cmd->data;
 	req = cmd->mrq;
@@ -621,20 +687,31 @@ ti_mmchs_start_cmd(struct ti_mmchs_softc
 			return;
 		}
 
+#ifndef SOC_TI_AM335X
 		/* Calculate the packet size, the max packet size is 512 bytes
 		 * (or 128 32-bit elements).
 		 */
 		pktsize = min((data->len / 4), (512 / 4));
-
+#endif
 		/* Sync the DMA buffer and setup the DMA controller */
 		if (data->flags & MMC_DATA_READ) {
 			bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREREAD);
+#ifdef SOC_TI_AM335X
+			ti_mmchs_edma3_rx_xfer_setup(sc, sc->sc_data_reg_paddr, 
+			    paddr, data->len, 1);
+#else
 			ti_sdma_start_xfer_packet(sc->sc_dmach_rd, sc->sc_data_reg_paddr,
 			    paddr, 1, (data->len / 4), pktsize);
+#endif
 		} else {
 			bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREWRITE);
+#ifdef SOC_TI_AM335X
+			ti_mmchs_edma3_tx_xfer_setup(sc, paddr,
+			    sc->sc_data_reg_paddr, data->len, 1);
+#else
 			ti_sdma_start_xfer_packet(sc->sc_dmach_wr, paddr,
 			    sc->sc_data_reg_paddr, 1, (data->len / 4), pktsize);
+#endif
 		}
 
 		/* Increase the mapped count */
@@ -891,7 +968,9 @@ ti_mmchs_update_ios(device_t brdev, devi
 	uint32_t hctl_reg;
 	uint32_t con_reg;
 	uint32_t sysctl_reg;
+#ifndef SOC_TI_AM335X
 	uint16_t mv;
+#endif
 	unsigned long timeout;
 	int do_card_init = 0;
 
@@ -932,19 +1011,26 @@ ti_mmchs_update_ios(device_t brdev, devi
 			hctl_reg &= ~(MMCHS_HCTL_SDVS_MASK | MMCHS_HCTL_SDBP);
 
 			if ((ios->vdd == -1) || (ios->vdd >= vdd_240)) {
+#ifndef SOC_TI_AM335X
 				mv = 3000;
+#endif
 				hctl_reg |= MMCHS_HCTL_SDVS_V30;
 			} else {
+#ifndef SOC_TI_AM335X
 				mv = 1800;
+#endif
 				hctl_reg |= MMCHS_HCTL_SDVS_V18;
 			}
 
 			ti_mmchs_write_4(sc, MMCHS_HCTL, hctl_reg);
 
+#ifdef SOC_TI_AM335X
+			printf("%s: TWL unimplemented\n", __func__);
+#else
 			/* Set the desired voltage on the regulator */
 			if (sc->sc_vreg_dev && sc->sc_vreg_name)
 				twl_vreg_set_voltage(sc->sc_vreg_dev, sc->sc_vreg_name, mv);
-
+#endif
 			/* Enable the bus power */
 			ti_mmchs_write_4(sc, MMCHS_HCTL, (hctl_reg | MMCHS_HCTL_SDBP));
 			timeout = hz;
@@ -959,10 +1045,13 @@ ti_mmchs_update_ios(device_t brdev, devi
 			hctl_reg = ti_mmchs_read_4(sc, MMCHS_HCTL);
 			ti_mmchs_write_4(sc, MMCHS_HCTL, (hctl_reg & ~MMCHS_HCTL_SDBP));
 
+#ifdef SOC_TI_AM335X
+			printf("%s: TWL unimplemented\n", __func__);
+#else
 			/* Turn the power off on the voltage regulator */
 			if (sc->sc_vreg_dev && sc->sc_vreg_name)
 				twl_vreg_set_voltage(sc->sc_vreg_dev, sc->sc_vreg_name, 0);
-
+#endif
 		} else if (ios->power_mode == power_on) {
 			/* Force a card re-initialisation sequence */
 			do_card_init = 1;
@@ -1341,10 +1430,28 @@ ti_mmchs_hw_fini(device_t dev)
 static int
 ti_mmchs_init_dma_channels(struct ti_mmchs_softc *sc)
 {
+#ifdef SOC_TI_AM335X
+	switch (sc->device_id) {
+		case 0:
+			sc->dma_tx_trig = TI_EDMA3_EVENT_SDTXEVT0;
+			sc->dma_rx_trig = TI_EDMA3_EVENT_SDRXEVT0;
+			break;
+		case 1:
+			sc->dma_tx_trig = TI_EDMA3_EVENT_SDTXEVT1;
+			sc->dma_rx_trig = TI_EDMA3_EVENT_SDRXEVT1;
+			break;
+		default:
+			return(-EINVAL);
+	}
+
+#define EVTQNUM		0
+	/* TODO EDMA3 have 3 queues, so we need some queue allocation call */
+	ti_edma3_init(EVTQNUM);
+	ti_edma3_request_dma_ch(sc->dma_tx_trig, sc->dma_tx_trig, EVTQNUM);
+	ti_edma3_request_dma_ch(sc->dma_rx_trig, sc->dma_rx_trig, EVTQNUM);
+#else
 	int err;
 	uint32_t rev;
-	int dma_rx_trig = -1;
-	int dma_tx_trig = -1;
 
 	/* Get the current chip revision */
 	rev = ti_revision();
@@ -1354,25 +1461,25 @@ ti_mmchs_init_dma_channels(struct ti_mmc
 	/* Get the DMA MMC triggers */
 	switch (sc->device_id) {
 		case 1:
-			dma_tx_trig = 60;
-			dma_rx_trig = 61;
+			sc->dma_tx_trig = 60;
+			sc->dma_rx_trig = 61;
 			break;
 		case 2:
-			dma_tx_trig = 46;
-			dma_rx_trig = 47;
+			sc->dma_tx_trig = 46;
+			sc->dma_rx_trig = 47;
 			break;
 		case 3:
-			dma_tx_trig = 76;
-			dma_rx_trig = 77;
+			sc->dma_tx_trig = 76;
+			sc->dma_rx_trig = 77;
 			break;
 		/* The following are OMAP4 only */
 		case 4:
-			dma_tx_trig = 56;
-			dma_rx_trig = 57;
+			sc->dma_tx_trig = 56;
+			sc->dma_rx_trig = 57;
 			break;
 		case 5:
-			dma_tx_trig = 58;
-			dma_rx_trig = 59;
+			sc->dma_tx_trig = 58;
+			sc->dma_rx_trig = 59;
 			break;
 		default:
 			return(-EINVAL);
@@ -1387,7 +1494,7 @@ ti_mmchs_init_dma_channels(struct ti_mmc
 	ti_sdma_set_xfer_burst(sc->sc_dmach_rd, TI_SDMA_BURST_NONE,
 	    TI_SDMA_BURST_64);
 	ti_sdma_set_xfer_data_type(sc->sc_dmach_rd, TI_SDMA_DATA_32BITS_SCALAR);
-	ti_sdma_sync_params(sc->sc_dmach_rd, dma_rx_trig,
+	ti_sdma_sync_params(sc->sc_dmach_rd, sc->dma_rx_trig,
 	    TI_SDMA_SYNC_PACKET | TI_SDMA_SYNC_TRIG_ON_SRC);
 	ti_sdma_set_addr_mode(sc->sc_dmach_rd, TI_SDMA_ADDR_CONSTANT,
 	    TI_SDMA_ADDR_POST_INCREMENT);
@@ -1401,11 +1508,11 @@ ti_mmchs_init_dma_channels(struct ti_mmc
 	ti_sdma_set_xfer_burst(sc->sc_dmach_wr, TI_SDMA_BURST_64,
 	    TI_SDMA_BURST_NONE);
 	ti_sdma_set_xfer_data_type(sc->sc_dmach_wr, TI_SDMA_DATA_32BITS_SCALAR);
-	ti_sdma_sync_params(sc->sc_dmach_wr, dma_tx_trig,
+	ti_sdma_sync_params(sc->sc_dmach_wr, sc->dma_tx_trig,
 	    TI_SDMA_SYNC_PACKET | TI_SDMA_SYNC_TRIG_ON_DST);
 	ti_sdma_set_addr_mode(sc->sc_dmach_wr, TI_SDMA_ADDR_POST_INCREMENT,
 	    TI_SDMA_ADDR_CONSTANT);
-
+#endif
 	return(0);
 }
 
@@ -1435,9 +1542,13 @@ ti_mmchs_deactivate(device_t dev)
 	/* Do the generic detach */
 	bus_generic_detach(sc->sc_dev);
 
+#ifdef SOC_TI_AM335X
+	printf("%s: DMA unimplemented\n", __func__);
+#else
 	/* Deactivate the DMA channels */
 	ti_sdma_deactivate_channel(sc->sc_dmach_rd);
 	ti_sdma_deactivate_channel(sc->sc_dmach_wr);
+#endif
 
 	/* Unmap the MMC controller registers */
 	if (sc->sc_mem_res != 0) {
@@ -1513,6 +1624,8 @@ ti_mmchs_activate(device_t dev)
 		sc->sc_reg_off = OMAP3_MMCHS_REG_OFFSET;
 	else if (ti_chip() == CHIP_OMAP_4)
 		sc->sc_reg_off = OMAP4_MMCHS_REG_OFFSET;
+	else if (ti_chip() == CHIP_AM335X)
+		sc->sc_reg_off = AM335X_MMCHS_REG_OFFSET;
 	else
 		panic("Unknown OMAP device\n");
 
@@ -1567,7 +1680,6 @@ ti_mmchs_attach(device_t dev)
 	phandle_t node;
 	pcell_t did;
 	int err;
-	device_t child;
 
 	/* Save the device and bus tag */
 	sc->sc_dev = dev;
@@ -1636,7 +1748,7 @@ ti_mmchs_attach(device_t dev)
 	sc->host.host_ocr = MMC_OCR_290_300 | MMC_OCR_300_310;
 	sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
 
-	child = device_add_child(dev, "mmc", 0);
+	device_add_child(dev, "mmc", 0);
 
 	device_set_ivars(dev, &sc->host);
 	err = bus_generic_attach(dev);
@@ -1646,10 +1758,14 @@ out:
 		TI_MMCHS_LOCK_DESTROY(sc);
 		ti_mmchs_deactivate(dev);
 
+#ifdef SOC_TI_AM335X
+		printf("%s: DMA unimplemented\n", __func__);
+#else
 		if (sc->sc_dmach_rd != (unsigned int)-1)
 			ti_sdma_deactivate_channel(sc->sc_dmach_rd);
 		if (sc->sc_dmach_wr != (unsigned int)-1)
 			ti_sdma_deactivate_channel(sc->sc_dmach_wr);
+#endif
 	}
 
 	return (err);
@@ -1667,13 +1783,19 @@ out:
 static int
 ti_mmchs_detach(device_t dev)
 {
+#ifndef SOC_TI_AM335X
 	struct ti_mmchs_softc *sc = device_get_softc(dev);
+#endif
 
 	ti_mmchs_hw_fini(dev);
 	ti_mmchs_deactivate(dev);
 
+#ifdef SOC_TI_AM335X
+		printf("%s: DMA unimplemented\n", __func__);
+#else
 	ti_sdma_deactivate_channel(sc->sc_dmach_wr);
 	ti_sdma_deactivate_channel(sc->sc_dmach_rd);
+#endif
 
 	return (0);
 }
@@ -1707,7 +1829,11 @@ static devclass_t ti_mmchs_devclass;
 
 DRIVER_MODULE(ti_mmchs, simplebus, ti_mmchs_driver, ti_mmchs_devclass, 0, 0);
 MODULE_DEPEND(ti_mmchs, ti_prcm, 1, 1, 1);
+#ifdef SOC_TI_AM335X
+MODULE_DEPEND(ti_mmchs, ti_edma, 1, 1, 1);
+#else
 MODULE_DEPEND(ti_mmchs, ti_sdma, 1, 1, 1);
+#endif
 MODULE_DEPEND(ti_mmchs, ti_gpio, 1, 1, 1);
 
 /* FIXME: MODULE_DEPEND(ti_mmchs, twl_vreg, 1, 1, 1); */

Modified: projects/armv6/sys/arm/ti/ti_mmchs.h
==============================================================================
--- projects/armv6/sys/arm/ti/ti_mmchs.h	Mon Apr 16 15:08:01 2012	(r234343)
+++ projects/armv6/sys/arm/ti/ti_mmchs.h	Mon Apr 16 15:43:31 2012	(r234344)
@@ -62,6 +62,7 @@
 /* OMAP4 and OMAP4 have different register addresses */
 #define OMAP3_MMCHS_REG_OFFSET      0x000
 #define OMAP4_MMCHS_REG_OFFSET      0x100
+#define AM335X_MMCHS_REG_OFFSET     0x100
 
 /* Register bit settings */
 #define MMCHS_STAT_BADA             (1UL << 29)

Modified: projects/armv6/sys/boot/fdt/dts/beaglebone.dts
==============================================================================
--- projects/armv6/sys/boot/fdt/dts/beaglebone.dts	Mon Apr 16 15:08:01 2012	(r234343)
+++ projects/armv6/sys/boot/fdt/dts/beaglebone.dts	Mon Apr 16 15:43:31 2012	(r234344)
@@ -125,7 +125,6 @@
 				0x481AE000 0x1000 >;
 			interrupts = < 17 19 21 23 >;
 			interrupt-parent = <&AINTC>;
-			mmchs-device-id = <0>;
 		};
 
 
@@ -138,6 +137,24 @@
 			clock-frequency = < 48000000 >; /* FIXME */
 		};
 
+		edma3@49000000 {
+			compatible = "ti,edma3";
+			reg =<	0x49000000 0x100000	/* Channel Controller Regs */
+				0x49800000 0x100000	/* Transfer Controller 0 Regs */
+				0x49900000 0x100000	/* Transfer Controller 1 Regs */
+				0x49a00000 0x100000 >;	/* Transfer Controller 2 Regs */
+			interrupts = <12 13 14>;
+			interrupt-parent = <&AINTC>;
+		};
+
+		mmchs0@4809C000 {
+			compatible = "ti,mmchs";
+			reg =<0x48060000 0x1000 >;
+			interrupts = <64>;
+			interrupt-parent = <&AINTC>;
+			mmchs-device-id = <0>;
+		};
+
 		enet0: ethernet@4A100000 {
 			#address-cells = <1>;
 			#size-cells = <1>;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204161543.q3GFhWZ8039848>