From owner-svn-src-projects@FreeBSD.ORG Mon Apr 16 15:43:32 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 91AE4106566B; Mon, 16 Apr 2012 15:43:32 +0000 (UTC) (envelope-from dmarion@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7AED18FC17; Mon, 16 Apr 2012 15:43:32 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q3GFhWgE039855; Mon, 16 Apr 2012 15:43:32 GMT (envelope-from dmarion@svn.freebsd.org) Received: (from dmarion@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q3GFhWZ8039848; Mon, 16 Apr 2012 15:43:32 GMT (envelope-from dmarion@svn.freebsd.org) Message-Id: <201204161543.q3GFhWZ8039848@svn.freebsd.org> From: Damjan Marion Date: Mon, 16 Apr 2012 15:43:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234344 - in projects/armv6/sys: arm/ti arm/ti/am335x boot/fdt/dts X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Apr 2012 15:43:32 -0000 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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#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 + * 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 +#include #include #include #include @@ -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>;