1*f3a72e40SRuslan Bukin /*- 2*f3a72e40SRuslan Bukin * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 3*f3a72e40SRuslan Bukin * All rights reserved. 4*f3a72e40SRuslan Bukin * 5*f3a72e40SRuslan Bukin * Redistribution and use in source and binary forms, with or without 6*f3a72e40SRuslan Bukin * modification, are permitted provided that the following conditions 7*f3a72e40SRuslan Bukin * are met: 8*f3a72e40SRuslan Bukin * 1. Redistributions of source code must retain the above copyright 9*f3a72e40SRuslan Bukin * notice, this list of conditions and the following disclaimer. 10*f3a72e40SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 11*f3a72e40SRuslan Bukin * notice, this list of conditions and the following disclaimer in the 12*f3a72e40SRuslan Bukin * documentation and/or other materials provided with the distribution. 13*f3a72e40SRuslan Bukin * 14*f3a72e40SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*f3a72e40SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*f3a72e40SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*f3a72e40SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*f3a72e40SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*f3a72e40SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*f3a72e40SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*f3a72e40SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*f3a72e40SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*f3a72e40SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*f3a72e40SRuslan Bukin * SUCH DAMAGE. 25*f3a72e40SRuslan Bukin */ 26*f3a72e40SRuslan Bukin 27*f3a72e40SRuslan Bukin /* 28*f3a72e40SRuslan Bukin * Vybrid Family Enhanced Direct Memory Access Controller (eDMA) 29*f3a72e40SRuslan Bukin * Chapter 21, Vybrid Reference Manual, Rev. 5, 07/2013 30*f3a72e40SRuslan Bukin */ 31*f3a72e40SRuslan Bukin 32*f3a72e40SRuslan Bukin #include <sys/cdefs.h> 33*f3a72e40SRuslan Bukin __FBSDID("$FreeBSD$"); 34*f3a72e40SRuslan Bukin 35*f3a72e40SRuslan Bukin #include <sys/param.h> 36*f3a72e40SRuslan Bukin #include <sys/systm.h> 37*f3a72e40SRuslan Bukin #include <sys/bus.h> 38*f3a72e40SRuslan Bukin #include <sys/kernel.h> 39*f3a72e40SRuslan Bukin #include <sys/module.h> 40*f3a72e40SRuslan Bukin #include <sys/malloc.h> 41*f3a72e40SRuslan Bukin #include <sys/rman.h> 42*f3a72e40SRuslan Bukin #include <sys/timeet.h> 43*f3a72e40SRuslan Bukin #include <sys/timetc.h> 44*f3a72e40SRuslan Bukin #include <sys/watchdog.h> 45*f3a72e40SRuslan Bukin 46*f3a72e40SRuslan Bukin #include <dev/fdt/fdt_common.h> 47*f3a72e40SRuslan Bukin #include <dev/ofw/openfirm.h> 48*f3a72e40SRuslan Bukin #include <dev/ofw/ofw_bus.h> 49*f3a72e40SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h> 50*f3a72e40SRuslan Bukin 51*f3a72e40SRuslan Bukin #include <machine/bus.h> 52*f3a72e40SRuslan Bukin #include <machine/fdt.h> 53*f3a72e40SRuslan Bukin #include <machine/cpu.h> 54*f3a72e40SRuslan Bukin #include <machine/intr.h> 55*f3a72e40SRuslan Bukin 56*f3a72e40SRuslan Bukin #include <arm/freescale/vybrid/vf_edma.h> 57*f3a72e40SRuslan Bukin #include <arm/freescale/vybrid/vf_dmamux.h> 58*f3a72e40SRuslan Bukin #include <arm/freescale/vybrid/vf_common.h> 59*f3a72e40SRuslan Bukin 60*f3a72e40SRuslan Bukin struct edma_channel { 61*f3a72e40SRuslan Bukin uint32_t enabled; 62*f3a72e40SRuslan Bukin uint32_t mux_num; 63*f3a72e40SRuslan Bukin uint32_t mux_src; 64*f3a72e40SRuslan Bukin uint32_t mux_chn; 65*f3a72e40SRuslan Bukin uint32_t (*ih) (void *, int); 66*f3a72e40SRuslan Bukin void *ih_user; 67*f3a72e40SRuslan Bukin }; 68*f3a72e40SRuslan Bukin 69*f3a72e40SRuslan Bukin static struct edma_channel edma_map[EDMA_NUM_CHANNELS]; 70*f3a72e40SRuslan Bukin 71*f3a72e40SRuslan Bukin static struct resource_spec edma_spec[] = { 72*f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 0, RF_ACTIVE }, 73*f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* TCD */ 74*f3a72e40SRuslan Bukin { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Transfer complete */ 75*f3a72e40SRuslan Bukin { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Error Interrupt */ 76*f3a72e40SRuslan Bukin { -1, 0 } 77*f3a72e40SRuslan Bukin }; 78*f3a72e40SRuslan Bukin 79*f3a72e40SRuslan Bukin static int 80*f3a72e40SRuslan Bukin edma_probe(device_t dev) 81*f3a72e40SRuslan Bukin { 82*f3a72e40SRuslan Bukin 83*f3a72e40SRuslan Bukin if (!ofw_bus_status_okay(dev)) 84*f3a72e40SRuslan Bukin return (ENXIO); 85*f3a72e40SRuslan Bukin 86*f3a72e40SRuslan Bukin if (!ofw_bus_is_compatible(dev, "fsl,mvf600-edma")) 87*f3a72e40SRuslan Bukin return (ENXIO); 88*f3a72e40SRuslan Bukin 89*f3a72e40SRuslan Bukin device_set_desc(dev, "Vybrid Family eDMA Controller"); 90*f3a72e40SRuslan Bukin return (BUS_PROBE_DEFAULT); 91*f3a72e40SRuslan Bukin } 92*f3a72e40SRuslan Bukin 93*f3a72e40SRuslan Bukin static void 94*f3a72e40SRuslan Bukin edma_transfer_complete_intr(void *arg) 95*f3a72e40SRuslan Bukin { 96*f3a72e40SRuslan Bukin struct edma_channel *ch; 97*f3a72e40SRuslan Bukin struct edma_softc *sc; 98*f3a72e40SRuslan Bukin int interrupts; 99*f3a72e40SRuslan Bukin int i; 100*f3a72e40SRuslan Bukin 101*f3a72e40SRuslan Bukin sc = arg; 102*f3a72e40SRuslan Bukin 103*f3a72e40SRuslan Bukin interrupts = READ4(sc, DMA_INT); 104*f3a72e40SRuslan Bukin WRITE1(sc, DMA_CINT, CINT_CAIR); 105*f3a72e40SRuslan Bukin 106*f3a72e40SRuslan Bukin for (i = 0; i < EDMA_NUM_CHANNELS; i++) { 107*f3a72e40SRuslan Bukin if (interrupts & (0x1 << i)) { 108*f3a72e40SRuslan Bukin ch = &edma_map[i]; 109*f3a72e40SRuslan Bukin if (ch->enabled == 1) { 110*f3a72e40SRuslan Bukin if (ch->ih != NULL) { 111*f3a72e40SRuslan Bukin ch->ih(ch->ih_user, i); 112*f3a72e40SRuslan Bukin } 113*f3a72e40SRuslan Bukin } 114*f3a72e40SRuslan Bukin } 115*f3a72e40SRuslan Bukin } 116*f3a72e40SRuslan Bukin } 117*f3a72e40SRuslan Bukin 118*f3a72e40SRuslan Bukin static void 119*f3a72e40SRuslan Bukin edma_err_intr(void *arg) 120*f3a72e40SRuslan Bukin { 121*f3a72e40SRuslan Bukin struct edma_softc *sc; 122*f3a72e40SRuslan Bukin int reg; 123*f3a72e40SRuslan Bukin 124*f3a72e40SRuslan Bukin sc = arg; 125*f3a72e40SRuslan Bukin 126*f3a72e40SRuslan Bukin reg = READ4(sc, DMA_ERR); 127*f3a72e40SRuslan Bukin 128*f3a72e40SRuslan Bukin #if 0 129*f3a72e40SRuslan Bukin device_printf(sc->dev, "DMA_ERR 0x%08x, ES 0x%08x\n", 130*f3a72e40SRuslan Bukin reg, READ4(sc, DMA_ES)); 131*f3a72e40SRuslan Bukin #endif 132*f3a72e40SRuslan Bukin 133*f3a72e40SRuslan Bukin WRITE1(sc, DMA_CERR, CERR_CAEI); 134*f3a72e40SRuslan Bukin } 135*f3a72e40SRuslan Bukin 136*f3a72e40SRuslan Bukin static int 137*f3a72e40SRuslan Bukin channel_free(struct edma_softc *sc, int chnum) 138*f3a72e40SRuslan Bukin { 139*f3a72e40SRuslan Bukin struct edma_channel *ch; 140*f3a72e40SRuslan Bukin 141*f3a72e40SRuslan Bukin ch = &edma_map[chnum]; 142*f3a72e40SRuslan Bukin ch->enabled = 0; 143*f3a72e40SRuslan Bukin 144*f3a72e40SRuslan Bukin dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 0); 145*f3a72e40SRuslan Bukin 146*f3a72e40SRuslan Bukin return (0); 147*f3a72e40SRuslan Bukin } 148*f3a72e40SRuslan Bukin 149*f3a72e40SRuslan Bukin static int 150*f3a72e40SRuslan Bukin channel_configure(struct edma_softc *sc, int mux_grp, int mux_src) 151*f3a72e40SRuslan Bukin { 152*f3a72e40SRuslan Bukin struct edma_channel *ch; 153*f3a72e40SRuslan Bukin int channel_first; 154*f3a72e40SRuslan Bukin int mux_num; 155*f3a72e40SRuslan Bukin int chnum; 156*f3a72e40SRuslan Bukin int i; 157*f3a72e40SRuslan Bukin 158*f3a72e40SRuslan Bukin if ((sc->device_id == 0 && mux_grp == 1) || \ 159*f3a72e40SRuslan Bukin (sc->device_id == 1 && mux_grp == 0)) { 160*f3a72e40SRuslan Bukin channel_first = NCHAN_PER_MUX; 161*f3a72e40SRuslan Bukin mux_num = (sc->device_id * 2) + 1; 162*f3a72e40SRuslan Bukin } else { 163*f3a72e40SRuslan Bukin channel_first = 0; 164*f3a72e40SRuslan Bukin mux_num = sc->device_id * 2; 165*f3a72e40SRuslan Bukin }; 166*f3a72e40SRuslan Bukin 167*f3a72e40SRuslan Bukin /* Take first unused eDMA channel */ 168*f3a72e40SRuslan Bukin ch = NULL; 169*f3a72e40SRuslan Bukin for (i = channel_first; i < (channel_first + NCHAN_PER_MUX); i++) { 170*f3a72e40SRuslan Bukin ch = &edma_map[i]; 171*f3a72e40SRuslan Bukin if (ch->enabled == 0) { 172*f3a72e40SRuslan Bukin break; 173*f3a72e40SRuslan Bukin } 174*f3a72e40SRuslan Bukin ch = NULL; 175*f3a72e40SRuslan Bukin }; 176*f3a72e40SRuslan Bukin 177*f3a72e40SRuslan Bukin if (ch == NULL) { 178*f3a72e40SRuslan Bukin /* Can't find free channel */ 179*f3a72e40SRuslan Bukin return (-1); 180*f3a72e40SRuslan Bukin }; 181*f3a72e40SRuslan Bukin 182*f3a72e40SRuslan Bukin chnum = i; 183*f3a72e40SRuslan Bukin 184*f3a72e40SRuslan Bukin ch->enabled = 1; 185*f3a72e40SRuslan Bukin ch->mux_num = mux_num; 186*f3a72e40SRuslan Bukin ch->mux_src = mux_src; 187*f3a72e40SRuslan Bukin ch->mux_chn = (chnum - channel_first); /* 0 to 15 */ 188*f3a72e40SRuslan Bukin 189*f3a72e40SRuslan Bukin dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 1); 190*f3a72e40SRuslan Bukin 191*f3a72e40SRuslan Bukin return (chnum); 192*f3a72e40SRuslan Bukin } 193*f3a72e40SRuslan Bukin 194*f3a72e40SRuslan Bukin static int 195*f3a72e40SRuslan Bukin dma_stop(struct edma_softc *sc, int chnum) 196*f3a72e40SRuslan Bukin { 197*f3a72e40SRuslan Bukin int reg; 198*f3a72e40SRuslan Bukin 199*f3a72e40SRuslan Bukin reg = READ4(sc, DMA_ERQ); 200*f3a72e40SRuslan Bukin reg &= ~(0x1 << chnum); 201*f3a72e40SRuslan Bukin WRITE4(sc, DMA_ERQ, reg); 202*f3a72e40SRuslan Bukin 203*f3a72e40SRuslan Bukin return (0); 204*f3a72e40SRuslan Bukin } 205*f3a72e40SRuslan Bukin 206*f3a72e40SRuslan Bukin static int 207*f3a72e40SRuslan Bukin dma_setup(struct edma_softc *sc, struct tcd_conf *tcd) 208*f3a72e40SRuslan Bukin { 209*f3a72e40SRuslan Bukin struct edma_channel *ch; 210*f3a72e40SRuslan Bukin int chnum; 211*f3a72e40SRuslan Bukin int reg; 212*f3a72e40SRuslan Bukin 213*f3a72e40SRuslan Bukin chnum = tcd->channel; 214*f3a72e40SRuslan Bukin 215*f3a72e40SRuslan Bukin ch = &edma_map[chnum]; 216*f3a72e40SRuslan Bukin ch->ih = tcd->ih; 217*f3a72e40SRuslan Bukin ch->ih_user = tcd->ih_user; 218*f3a72e40SRuslan Bukin 219*f3a72e40SRuslan Bukin TCD_WRITE4(sc, DMA_TCDn_SADDR(chnum), tcd->saddr); 220*f3a72e40SRuslan Bukin TCD_WRITE4(sc, DMA_TCDn_DADDR(chnum), tcd->daddr); 221*f3a72e40SRuslan Bukin 222*f3a72e40SRuslan Bukin reg = (tcd->smod << TCD_ATTR_SMOD_SHIFT); 223*f3a72e40SRuslan Bukin reg |= (tcd->dmod << TCD_ATTR_DMOD_SHIFT); 224*f3a72e40SRuslan Bukin reg |= (tcd->ssize << TCD_ATTR_SSIZE_SHIFT); 225*f3a72e40SRuslan Bukin reg |= (tcd->dsize << TCD_ATTR_DSIZE_SHIFT); 226*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_ATTR(chnum), reg); 227*f3a72e40SRuslan Bukin 228*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_SOFF(chnum), tcd->soff); 229*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_DOFF(chnum), tcd->doff); 230*f3a72e40SRuslan Bukin TCD_WRITE4(sc, DMA_TCDn_SLAST(chnum), tcd->slast); 231*f3a72e40SRuslan Bukin TCD_WRITE4(sc, DMA_TCDn_DLASTSGA(chnum), tcd->dlast_sga); 232*f3a72e40SRuslan Bukin TCD_WRITE4(sc, DMA_TCDn_NBYTES_MLOFFYES(chnum), tcd->nbytes); 233*f3a72e40SRuslan Bukin 234*f3a72e40SRuslan Bukin reg = tcd->nmajor; /* Current Major Iteration Count */ 235*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_CITER_ELINKNO(chnum), reg); 236*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_BITER_ELINKNO(chnum), reg); 237*f3a72e40SRuslan Bukin 238*f3a72e40SRuslan Bukin reg = (TCD_CSR_INTMAJOR); 239*f3a72e40SRuslan Bukin if(tcd->majorelink == 1) { 240*f3a72e40SRuslan Bukin reg |= TCD_CSR_MAJORELINK; 241*f3a72e40SRuslan Bukin reg |= (tcd->majorelinkch << TCD_CSR_MAJORELINKCH_SHIFT); 242*f3a72e40SRuslan Bukin } 243*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg); 244*f3a72e40SRuslan Bukin 245*f3a72e40SRuslan Bukin /* Enable requests */ 246*f3a72e40SRuslan Bukin reg = READ4(sc, DMA_ERQ); 247*f3a72e40SRuslan Bukin reg |= (0x1 << chnum); 248*f3a72e40SRuslan Bukin WRITE4(sc, DMA_ERQ, reg); 249*f3a72e40SRuslan Bukin 250*f3a72e40SRuslan Bukin /* Enable error interrupts */ 251*f3a72e40SRuslan Bukin reg = READ4(sc, DMA_EEI); 252*f3a72e40SRuslan Bukin reg |= (0x1 << chnum); 253*f3a72e40SRuslan Bukin WRITE4(sc, DMA_EEI, reg); 254*f3a72e40SRuslan Bukin 255*f3a72e40SRuslan Bukin return (0); 256*f3a72e40SRuslan Bukin } 257*f3a72e40SRuslan Bukin 258*f3a72e40SRuslan Bukin static int 259*f3a72e40SRuslan Bukin dma_request(struct edma_softc *sc, int chnum) 260*f3a72e40SRuslan Bukin { 261*f3a72e40SRuslan Bukin int reg; 262*f3a72e40SRuslan Bukin 263*f3a72e40SRuslan Bukin /* Start */ 264*f3a72e40SRuslan Bukin reg = TCD_READ2(sc, DMA_TCDn_CSR(chnum)); 265*f3a72e40SRuslan Bukin reg |= TCD_CSR_START; 266*f3a72e40SRuslan Bukin TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg); 267*f3a72e40SRuslan Bukin 268*f3a72e40SRuslan Bukin return (0); 269*f3a72e40SRuslan Bukin } 270*f3a72e40SRuslan Bukin 271*f3a72e40SRuslan Bukin static int 272*f3a72e40SRuslan Bukin edma_attach(device_t dev) 273*f3a72e40SRuslan Bukin { 274*f3a72e40SRuslan Bukin struct edma_softc *sc; 275*f3a72e40SRuslan Bukin phandle_t node; 276*f3a72e40SRuslan Bukin int dts_value; 277*f3a72e40SRuslan Bukin int len; 278*f3a72e40SRuslan Bukin 279*f3a72e40SRuslan Bukin sc = device_get_softc(dev); 280*f3a72e40SRuslan Bukin sc->dev = dev; 281*f3a72e40SRuslan Bukin 282*f3a72e40SRuslan Bukin if ((node = ofw_bus_get_node(sc->dev)) == -1) 283*f3a72e40SRuslan Bukin return (ENXIO); 284*f3a72e40SRuslan Bukin 285*f3a72e40SRuslan Bukin if ((len = OF_getproplen(node, "device-id")) <= 0) 286*f3a72e40SRuslan Bukin return (ENXIO); 287*f3a72e40SRuslan Bukin 288*f3a72e40SRuslan Bukin OF_getprop(node, "device-id", &dts_value, len); 289*f3a72e40SRuslan Bukin sc->device_id = fdt32_to_cpu(dts_value); 290*f3a72e40SRuslan Bukin 291*f3a72e40SRuslan Bukin sc->dma_stop = dma_stop; 292*f3a72e40SRuslan Bukin sc->dma_setup = dma_setup; 293*f3a72e40SRuslan Bukin sc->dma_request = dma_request; 294*f3a72e40SRuslan Bukin sc->channel_configure = channel_configure; 295*f3a72e40SRuslan Bukin sc->channel_free = channel_free; 296*f3a72e40SRuslan Bukin 297*f3a72e40SRuslan Bukin if (bus_alloc_resources(dev, edma_spec, sc->res)) { 298*f3a72e40SRuslan Bukin device_printf(dev, "could not allocate resources\n"); 299*f3a72e40SRuslan Bukin return (ENXIO); 300*f3a72e40SRuslan Bukin } 301*f3a72e40SRuslan Bukin 302*f3a72e40SRuslan Bukin /* Memory interface */ 303*f3a72e40SRuslan Bukin sc->bst = rman_get_bustag(sc->res[0]); 304*f3a72e40SRuslan Bukin sc->bsh = rman_get_bushandle(sc->res[0]); 305*f3a72e40SRuslan Bukin sc->bst_tcd = rman_get_bustag(sc->res[1]); 306*f3a72e40SRuslan Bukin sc->bsh_tcd = rman_get_bushandle(sc->res[1]); 307*f3a72e40SRuslan Bukin 308*f3a72e40SRuslan Bukin /* Setup interrupt handlers */ 309*f3a72e40SRuslan Bukin if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE, 310*f3a72e40SRuslan Bukin NULL, edma_transfer_complete_intr, sc, &sc->tc_ih)) { 311*f3a72e40SRuslan Bukin device_printf(dev, "Unable to alloc DMA intr resource.\n"); 312*f3a72e40SRuslan Bukin return (ENXIO); 313*f3a72e40SRuslan Bukin } 314*f3a72e40SRuslan Bukin 315*f3a72e40SRuslan Bukin if (bus_setup_intr(dev, sc->res[3], INTR_TYPE_BIO | INTR_MPSAFE, 316*f3a72e40SRuslan Bukin NULL, edma_err_intr, sc, &sc->err_ih)) { 317*f3a72e40SRuslan Bukin device_printf(dev, "Unable to alloc DMA Err intr resource.\n"); 318*f3a72e40SRuslan Bukin return (ENXIO); 319*f3a72e40SRuslan Bukin } 320*f3a72e40SRuslan Bukin 321*f3a72e40SRuslan Bukin return (0); 322*f3a72e40SRuslan Bukin } 323*f3a72e40SRuslan Bukin 324*f3a72e40SRuslan Bukin static device_method_t edma_methods[] = { 325*f3a72e40SRuslan Bukin DEVMETHOD(device_probe, edma_probe), 326*f3a72e40SRuslan Bukin DEVMETHOD(device_attach, edma_attach), 327*f3a72e40SRuslan Bukin { 0, 0 } 328*f3a72e40SRuslan Bukin }; 329*f3a72e40SRuslan Bukin 330*f3a72e40SRuslan Bukin static driver_t edma_driver = { 331*f3a72e40SRuslan Bukin "edma", 332*f3a72e40SRuslan Bukin edma_methods, 333*f3a72e40SRuslan Bukin sizeof(struct edma_softc), 334*f3a72e40SRuslan Bukin }; 335*f3a72e40SRuslan Bukin 336*f3a72e40SRuslan Bukin static devclass_t edma_devclass; 337*f3a72e40SRuslan Bukin 338*f3a72e40SRuslan Bukin DRIVER_MODULE(edma, simplebus, edma_driver, edma_devclass, 0, 0); 339