svn commit: r234344 - in projects/armv6/sys: arm/ti arm/ti/am335x
boot/fdt/dts
Damjan Marion
dmarion at FreeBSD.org
Mon Apr 16 15:43:32 UTC 2012
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 at 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 at 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 at 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 at 4809C000 {
+ compatible = "ti,mmchs";
+ reg =<0x48060000 0x1000 >;
+ interrupts = <64>;
+ interrupt-parent = <&AINTC>;
+ mmchs-device-id = <0>;
+ };
+
enet0: ethernet at 4A100000 {
#address-cells = <1>;
#size-cells = <1>;
More information about the svn-src-projects
mailing list