Tue Apr 14 18:37:43 2015 UTC ()
Add a driver for the Enhanced Direct Memory Access controller found
in the AM335x SoC. Written by Jared D. McNeill, with some final debug
by me.
Supports only DMA (not QDMA) yet, and there's no support for DMA event
matrix yet (this means that only primary DMA events can be used)
(bouyer)
diff -r1.29 -r1.30 src/sys/arch/arm/omap/files.omap2
diff -r1.21 -r1.22 src/sys/arch/arm/omap/omap2_obio.c
diff -r1.2 -r1.3 src/sys/arch/arm/omap/omap2_obiovar.h
diff -r1.28 -r1.29 src/sys/arch/arm/omap/omap2_reg.h
diff -r0 -r1.1 src/sys/arch/arm/omap/omap_edma.c
diff -r0 -r1.1 src/sys/arch/arm/omap/omap_edma.c.orig
diff -r0 -r1.1 src/sys/arch/arm/omap/omap_edma.h
diff -r0 -r1.1 src/sys/arch/arm/omap/omap_edma.h.orig
--- src/sys/arch/arm/omap/Attic/files.omap2 2014/08/22 19:44:04 1.29
+++ src/sys/arch/arm/omap/Attic/files.omap2 2015/04/14 18:37:43 1.30
| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | # $NetBSD: files.omap2,v 1.29 2014/08/22 19:44:04 jakllsch Exp $ | | 1 | # $NetBSD: files.omap2,v 1.30 2015/04/14 18:37:43 bouyer Exp $ |
2 | # | | 2 | # |
3 | # Configuration info for Texas Instruments OMAP2/OMAP3 CPU support | | 3 | # Configuration info for Texas Instruments OMAP2/OMAP3 CPU support |
4 | # Based on xscale/files.pxa2x0 | | 4 | # Based on xscale/files.pxa2x0 |
5 | # | | 5 | # |
6 | | | 6 | |
7 | include "arch/arm/pic/files.pic" | | 7 | include "arch/arm/pic/files.pic" |
8 | include "arch/arm/cortex/files.cortex" | | 8 | include "arch/arm/cortex/files.cortex" |
9 | | | 9 | |
10 | file arch/arm/arm32/irq_dispatch.S | | 10 | file arch/arm/arm32/irq_dispatch.S |
11 | file arch/arm/omap/omap_dma.c | | 11 | file arch/arm/omap/omap_dma.c |
12 | | | 12 | |
13 | # Memory size in megabytes | | 13 | # Memory size in megabytes |
14 | defparam opt_omap.h MEMSIZE | | 14 | defparam opt_omap.h MEMSIZE |
| @@ -22,27 +22,27 @@ defflag opt_omap.h OMAP_2430: OMAP_2X | | | @@ -22,27 +22,27 @@ defflag opt_omap.h OMAP_2430: OMAP_2X |
22 | defflag opt_omap.h OMAP_2420: OMAP_2XXX | | 22 | defflag opt_omap.h OMAP_2420: OMAP_2XXX |
23 | defflag opt_omap.h OMAP_3XXX: OMAP3 | | 23 | defflag opt_omap.h OMAP_3XXX: OMAP3 |
24 | defflag opt_omap.h OMAP_3430: OMAP_3XXX | | 24 | defflag opt_omap.h OMAP_3430: OMAP_3XXX |
25 | defflag opt_omap.h OMAP_3530: OMAP_3XXX | | 25 | defflag opt_omap.h OMAP_3530: OMAP_3XXX |
26 | defflag opt_omap.h OMAP_4XXX: OMAP4 | | 26 | defflag opt_omap.h OMAP_4XXX: OMAP4 |
27 | defflag opt_omap.h OMAP_4430: OMAP_4XXX | | 27 | defflag opt_omap.h OMAP_4430: OMAP_4XXX |
28 | defflag opt_omap.h OMAP_4460: OMAP_4XXX | | 28 | defflag opt_omap.h OMAP_4460: OMAP_4XXX |
29 | defflag opt_omap.h OMAP_5XXX: OMAP5 | | 29 | defflag opt_omap.h OMAP_5XXX: OMAP5 |
30 | defflag opt_omap.h OMAP_5430: OMAP_5XXX | | 30 | defflag opt_omap.h OMAP_5430: OMAP_5XXX |
31 | defflag opt_omap.h TI_AM335X: OMAP3 | | 31 | defflag opt_omap.h TI_AM335X: OMAP3 |
32 | defflag opt_omap.h TI_DM37XX: OMAP3 | | 32 | defflag opt_omap.h TI_DM37XX: OMAP3 |
33 | | | 33 | |
34 | # OBIO just an attach point | | 34 | # OBIO just an attach point |
35 | device obio { [addr=-1], [size=0], [intr=-1], [mult=1], [intrbase=-1], [nobyteacc=0] | | 35 | device obio { [addr=-1], [size=0], [intr=-1], [mult=1], [intrbase=-1], [nobyteacc=0], [edmabase=-1] |
36 | } : bus_space_generic | | 36 | } : bus_space_generic |
37 | attach obio at mainbus | | 37 | attach obio at mainbus |
38 | file arch/arm/omap/omap2_obio.c obio needs-count | | 38 | file arch/arm/omap/omap2_obio.c obio needs-count |
39 | | | 39 | |
40 | # OBIO files | | 40 | # OBIO files |
41 | file arch/arm/omap/omap_space.c obio | | 41 | file arch/arm/omap/omap_space.c obio |
42 | file arch/arm/omap/omap_a2x_space.c obio | | 42 | file arch/arm/omap/omap_a2x_space.c obio |
43 | file arch/arm/arm/bus_space_a2x.S obio | | 43 | file arch/arm/arm/bus_space_a2x.S obio |
44 | file arch/arm/omap/omap_a4x_space.c obio | | 44 | file arch/arm/omap/omap_a4x_space.c obio |
45 | file arch/arm/arm/bus_space_a4x.S obio | | 45 | file arch/arm/arm/bus_space_a4x.S obio |
46 | | | 46 | |
47 | # TI Sitara control module | | 47 | # TI Sitara control module |
48 | device sitaracm | | 48 | device sitaracm |
| @@ -160,17 +160,21 @@ file arch/arm/omap/omapfb.c omapfb | | | @@ -160,17 +160,21 @@ file arch/arm/omap/omapfb.c omapfb |
160 | # TI AM335x framebuffer | | 160 | # TI AM335x framebuffer |
161 | device tifb: rasops32, rasops24, rasops16, rasops8, wsemuldisplaydev, vcons, edid | | 161 | device tifb: rasops32, rasops24, rasops16, rasops8, wsemuldisplaydev, vcons, edid |
162 | attach tifb at obio | | 162 | attach tifb at obio |
163 | file arch/arm/omap/tifb.c tifb | | 163 | file arch/arm/omap/tifb.c tifb |
164 | | | 164 | |
165 | device cpsw: ether, ifnet, arp, mii, mii_phy | | 165 | device cpsw: ether, ifnet, arp, mii, mii_phy |
166 | attach cpsw at obio | | 166 | attach cpsw at obio |
167 | file arch/arm/omap/if_cpsw.c cpsw | | 167 | file arch/arm/omap/if_cpsw.c cpsw |
168 | | | 168 | |
169 | device omapdma | | 169 | device omapdma |
170 | attach omapdma at obio | | 170 | attach omapdma at obio |
171 | file arch/arm/omap/omap3_sdma.c omapdma needs-flag | | 171 | file arch/arm/omap/omap3_sdma.c omapdma needs-flag |
172 | | | 172 | |
| | | 173 | device edma |
| | | 174 | attach edma at obio |
| | | 175 | file arch/arm/omap/omap_edma.c edma needs-flag |
| | | 176 | |
173 | # these bus space methods are not bus-specific ... | | 177 | # these bus space methods are not bus-specific ... |
174 | # | | 178 | # |
175 | file arch/arm/omap/omap_nobyteacc_space.c emifs | gpmc | | 179 | file arch/arm/omap/omap_nobyteacc_space.c emifs | gpmc |
176 | file arch/arm/omap/omap_nobyteacc_io.S emifs | gpmc | | 180 | file arch/arm/omap/omap_nobyteacc_io.S emifs | gpmc |
--- src/sys/arch/arm/omap/Attic/omap2_obio.c 2013/06/15 21:58:20 1.21
+++ src/sys/arch/arm/omap/Attic/omap2_obio.c 2015/04/14 18:37:43 1.22
| @@ -1,17 +1,17 @@ | | | @@ -1,17 +1,17 @@ |
1 | /* $Id: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $ */ | | 1 | /* $Id: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* adapted from: */ | | 3 | /* adapted from: */ |
4 | /* $NetBSD: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $ */ | | 4 | /* $NetBSD: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $ */ |
5 | | | 5 | |
6 | | | 6 | |
7 | /* | | 7 | /* |
8 | * Autoconfiguration support for the Texas Instruments OMAP "On Board" I/O. | | 8 | * Autoconfiguration support for the Texas Instruments OMAP "On Board" I/O. |
9 | * | | 9 | * |
10 | * Based on arm/omap/omap_emifs.c which in turn was derived | | 10 | * Based on arm/omap/omap_emifs.c which in turn was derived |
11 | * Based on arm/xscale/pxa2x0.c which in turn was derived | | 11 | * Based on arm/xscale/pxa2x0.c which in turn was derived |
12 | * from arm/sa11x0/sa11x0.c | | 12 | * from arm/sa11x0/sa11x0.c |
13 | * | | 13 | * |
14 | * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved. | | 14 | * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved. |
15 | * Written by Hiroyuki Bessho for Genetec Corporation. | | 15 | * Written by Hiroyuki Bessho for Genetec Corporation. |
16 | * | | 16 | * |
17 | * Redistribution and use in source and binary forms, with or without | | 17 | * Redistribution and use in source and binary forms, with or without |
| @@ -93,27 +93,27 @@ | | | @@ -93,27 +93,27 @@ |
93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
101 | * SUCH DAMAGE. | | 101 | * SUCH DAMAGE. |
102 | */ | | 102 | */ |
103 | | | 103 | |
104 | #include "opt_omap.h" | | 104 | #include "opt_omap.h" |
105 | #include <sys/cdefs.h> | | 105 | #include <sys/cdefs.h> |
106 | __KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.21 2013/06/15 21:58:20 matt Exp $"); | | 106 | __KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.22 2015/04/14 18:37:43 bouyer Exp $"); |
107 | | | 107 | |
108 | #include "locators.h" | | 108 | #include "locators.h" |
109 | #include "obio.h" | | 109 | #include "obio.h" |
110 | | | 110 | |
111 | #include <sys/param.h> | | 111 | #include <sys/param.h> |
112 | #include <sys/systm.h> | | 112 | #include <sys/systm.h> |
113 | #include <sys/device.h> | | 113 | #include <sys/device.h> |
114 | #include <sys/kernel.h> | | 114 | #include <sys/kernel.h> |
115 | #include <sys/reboot.h> | | 115 | #include <sys/reboot.h> |
116 | | | 116 | |
117 | #include <machine/cpu.h> | | 117 | #include <machine/cpu.h> |
118 | #include <sys/bus.h> | | 118 | #include <sys/bus.h> |
119 | | | 119 | |
| @@ -274,26 +274,27 @@ obio_search(device_t parent, cfdata_t cf | | | @@ -274,26 +274,27 @@ obio_search(device_t parent, cfdata_t cf |
274 | oa.obio_iot = &omap_a4x_bs_tag; | | 274 | oa.obio_iot = &omap_a4x_bs_tag; |
275 | break; | | 275 | break; |
276 | default: | | 276 | default: |
277 | panic("Unsupported EMIFS multiplier."); | | 277 | panic("Unsupported EMIFS multiplier."); |
278 | break; | | 278 | break; |
279 | } | | 279 | } |
280 | } | | 280 | } |
281 | | | 281 | |
282 | oa.obio_dmat = sc->sc_dmat; | | 282 | oa.obio_dmat = sc->sc_dmat; |
283 | oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; | | 283 | oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; |
284 | oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; | | 284 | oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; |
285 | oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; | | 285 | oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; |
286 | oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; | | 286 | oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; |
| | | 287 | oa.obio_edmabase = cf->cf_loc[OBIOCF_EDMABASE]; |
287 | | | 288 | |
288 | #if defined(OMAP2) | | 289 | #if defined(OMAP2) |
289 | if ((oa.obio_addr >= sc->sc_base) | | 290 | if ((oa.obio_addr >= sc->sc_base) |
290 | && (oa.obio_addr < (sc->sc_base + sc->sc_size))) { | | 291 | && (oa.obio_addr < (sc->sc_base + sc->sc_size))) { |
291 | /* XXX | | 292 | /* XXX |
292 | * if size was specified, then check it too | | 293 | * if size was specified, then check it too |
293 | * otherwise just assume it is OK | | 294 | * otherwise just assume it is OK |
294 | */ | | 295 | */ |
295 | if ((oa.obio_size != OBIOCF_SIZE_DEFAULT) | | 296 | if ((oa.obio_size != OBIOCF_SIZE_DEFAULT) |
296 | && ((oa.obio_addr + oa.obio_size) | | 297 | && ((oa.obio_addr + oa.obio_size) |
297 | >= (sc->sc_base + sc->sc_size))) | | 298 | >= (sc->sc_base + sc->sc_size))) |
298 | return 1; /* NG */ | | 299 | return 1; /* NG */ |
299 | if (config_match(parent, cf, &oa)) { | | 300 | if (config_match(parent, cf, &oa)) { |
| @@ -341,26 +342,27 @@ obio_find(device_t parent, cfdata_t cf, | | | @@ -341,26 +342,27 @@ obio_find(device_t parent, cfdata_t cf, |
341 | break; | | 342 | break; |
342 | case 4: | | 343 | case 4: |
343 | oa->obio_iot = &omap_a4x_bs_tag; | | 344 | oa->obio_iot = &omap_a4x_bs_tag; |
344 | break; | | 345 | break; |
345 | default: | | 346 | default: |
346 | panic("Unsupported EMIFS multiplier."); | | 347 | panic("Unsupported EMIFS multiplier."); |
347 | break; | | 348 | break; |
348 | } | | 349 | } |
349 | } | | 350 | } |
350 | oa->obio_addr = cf->cf_loc[OBIOCF_ADDR]; | | 351 | oa->obio_addr = cf->cf_loc[OBIOCF_ADDR]; |
351 | oa->obio_size = cf->cf_loc[OBIOCF_SIZE]; | | 352 | oa->obio_size = cf->cf_loc[OBIOCF_SIZE]; |
352 | oa->obio_intr = cf->cf_loc[OBIOCF_INTR]; | | 353 | oa->obio_intr = cf->cf_loc[OBIOCF_INTR]; |
353 | oa->obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; | | 354 | oa->obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; |
| | | 355 | oa->obio_edmabase = cf->cf_loc[OBIOCF_EDMABASE]; |
354 | | | 356 | |
355 | return config_match(parent, cf, oa); | | 357 | return config_match(parent, cf, oa); |
356 | } | | 358 | } |
357 | | | 359 | |
358 | #if 0 && NOMAP2ICU == 0 | | 360 | #if 0 && NOMAP2ICU == 0 |
359 | #error no avic present in config file | | 361 | #error no avic present in config file |
360 | #endif | | 362 | #endif |
361 | | | 363 | |
362 | static const struct { | | 364 | static const struct { |
363 | const char *name; | | 365 | const char *name; |
364 | bus_addr_t addr; | | 366 | bus_addr_t addr; |
365 | bool required; | | 367 | bool required; |
366 | } critical_devs[] = { | | 368 | } critical_devs[] = { |
| @@ -388,26 +390,27 @@ static const struct { | | | @@ -388,26 +390,27 @@ static const struct { |
388 | #if defined(GPIO7_BASE) | | 390 | #if defined(GPIO7_BASE) |
389 | { .name = "gpio7", .addr = GPIO7_BASE, .required = false }, | | 391 | { .name = "gpio7", .addr = GPIO7_BASE, .required = false }, |
390 | #endif | | 392 | #endif |
391 | #if defined(GPIO8_BASE) | | 393 | #if defined(GPIO8_BASE) |
392 | { .name = "gpio8", .addr = GPIO8_BASE, .required = false }, | | 394 | { .name = "gpio8", .addr = GPIO8_BASE, .required = false }, |
393 | #endif | | 395 | #endif |
394 | #if 0 | | 396 | #if 0 |
395 | { .name = "dmac", .addr = DMAC_BASE, .required = true }, | | 397 | { .name = "dmac", .addr = DMAC_BASE, .required = true }, |
396 | #endif | | 398 | #endif |
397 | #if defined(TI_AM335X) | | 399 | #if defined(TI_AM335X) |
398 | { .name = "omapicu", .addr = 0x48200000, .required = true }, | | 400 | { .name = "omapicu", .addr = 0x48200000, .required = true }, |
399 | { .name = "prcm", .addr = 0x44e00000, .required = true }, | | 401 | { .name = "prcm", .addr = 0x44e00000, .required = true }, |
400 | { .name = "sitaracm", .addr = 0x44e10000, .required = true }, | | 402 | { .name = "sitaracm", .addr = 0x44e10000, .required = true }, |
| | | 403 | { .name = "edma", .addr = 0x49000000, .required = false }, |
401 | #endif | | 404 | #endif |
402 | #if defined(OMAP_3530) | | 405 | #if defined(OMAP_3530) |
403 | { .name = "omapdma", .addr = OMAP3530_SDMA_BASE, .required = true }, | | 406 | { .name = "omapdma", .addr = OMAP3530_SDMA_BASE, .required = true }, |
404 | #endif | | 407 | #endif |
405 | }; | | 408 | }; |
406 | | | 409 | |
407 | static void | | 410 | static void |
408 | obio_attach_critical(struct obio_softc *sc) | | 411 | obio_attach_critical(struct obio_softc *sc) |
409 | { | | 412 | { |
410 | struct obio_attach_args oa; | | 413 | struct obio_attach_args oa; |
411 | cfdata_t cf; | | 414 | cfdata_t cf; |
412 | size_t i; | | 415 | size_t i; |
413 | | | 416 | |
--- src/sys/arch/arm/omap/Attic/omap2_obiovar.h 2012/09/05 00:19:59 1.2
+++ src/sys/arch/arm/omap/Attic/omap2_obiovar.h 2015/04/14 18:37:43 1.3
| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: omap2_obiovar.h,v 1.2 2012/09/05 00:19:59 matt Exp $ */ | | 1 | /* $NetBSD: omap2_obiovar.h,v 1.3 2015/04/14 18:37:43 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007 Microsoft | | 4 | * Copyright (c) 2007 Microsoft |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -30,26 +30,27 @@ | | | @@ -30,26 +30,27 @@ |
30 | */ | | 30 | */ |
31 | #ifndef _ARM_OMAP_OMAP2_OBIOVAR_H_ | | 31 | #ifndef _ARM_OMAP_OMAP2_OBIOVAR_H_ |
32 | #define _ARM_OMAP_OMAP2_OBIOVAR_H_ | | 32 | #define _ARM_OMAP_OMAP2_OBIOVAR_H_ |
33 | | | 33 | |
34 | struct obio_attach_args { | | 34 | struct obio_attach_args { |
35 | const char *obio_name; | | 35 | const char *obio_name; |
36 | bus_space_tag_t obio_iot; | | 36 | bus_space_tag_t obio_iot; |
37 | bus_addr_t obio_addr; | | 37 | bus_addr_t obio_addr; |
38 | bus_size_t obio_size; | | 38 | bus_size_t obio_size; |
39 | int obio_intr; | | 39 | int obio_intr; |
40 | bus_dma_tag_t obio_dmat; | | 40 | bus_dma_tag_t obio_dmat; |
41 | unsigned int obio_mult; | | 41 | unsigned int obio_mult; |
42 | unsigned int obio_intrbase; | | 42 | unsigned int obio_intrbase; |
| | | 43 | int obio_edmabase; |
43 | }; | | 44 | }; |
44 | | | 45 | |
45 | struct obio_softc { | | 46 | struct obio_softc { |
46 | device_t sc_dev; | | 47 | device_t sc_dev; |
47 | bus_dma_tag_t sc_dmat; | | 48 | bus_dma_tag_t sc_dmat; |
48 | bus_space_tag_t sc_iot; | | 49 | bus_space_tag_t sc_iot; |
49 | bus_space_handle_t sc_ioh; | | 50 | bus_space_handle_t sc_ioh; |
50 | bus_addr_t sc_base; | | 51 | bus_addr_t sc_base; |
51 | bus_size_t sc_size; | | 52 | bus_size_t sc_size; |
52 | device_t sc_obio_dev; | | 53 | device_t sc_obio_dev; |
53 | }; | | 54 | }; |
54 | | | 55 | |
55 | #endif /* _ARM_OMAP_OMAP2_OBIOVAR_H_ */ | | 56 | #endif /* _ARM_OMAP_OMAP2_OBIOVAR_H_ */ |
--- src/sys/arch/arm/omap/Attic/omap2_reg.h 2014/07/20 23:08:43 1.28
+++ src/sys/arch/arm/omap/Attic/omap2_reg.h 2015/04/14 18:37:43 1.29
| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: omap2_reg.h,v 1.28 2014/07/20 23:08:43 bouyer Exp $ */ | | 1 | /* $NetBSD: omap2_reg.h,v 1.29 2015/04/14 18:37:43 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007 Microsoft | | 4 | * Copyright (c) 2007 Microsoft |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -886,15 +886,30 @@ | | | @@ -886,15 +886,30 @@ |
886 | #define CTLMOD_CONTROL_STATUS_SYSBOOT1 __BITS(23,22) | | 886 | #define CTLMOD_CONTROL_STATUS_SYSBOOT1 __BITS(23,22) |
887 | | | 887 | |
888 | #define TI_AM335X_CTLMOD_DEVID 0x0600 | | 888 | #define TI_AM335X_CTLMOD_DEVID 0x0600 |
889 | #define TI_AM335X_CTLMOD_DEVID_REV(x) (((x) >> 28) & 0xf) | | 889 | #define TI_AM335X_CTLMOD_DEVID_REV(x) (((x) >> 28) & 0xf) |
890 | #endif | | 890 | #endif |
891 | #if defined(OMAP4) || defined(TI_AM335X) | | 891 | #if defined(OMAP4) || defined(TI_AM335X) |
892 | #define EMIF_SDRAM_CONFIG 8 | | 892 | #define EMIF_SDRAM_CONFIG 8 |
893 | #define SDRAM_CONFIG_WIDTH __BITS(15,14) | | 893 | #define SDRAM_CONFIG_WIDTH __BITS(15,14) |
894 | #define SDRAM_CONFIG_RSIZE __BITS(9,7) | | 894 | #define SDRAM_CONFIG_RSIZE __BITS(9,7) |
895 | #define SDRAM_CONFIG_IBANK __BITS(6,4) | | 895 | #define SDRAM_CONFIG_IBANK __BITS(6,4) |
896 | #define SDRAM_CONFIG_EBANK __BIT(3) | | 896 | #define SDRAM_CONFIG_EBANK __BIT(3) |
897 | #define SDRAM_CONFIG_PAGESIZE __BITS(2,0) | | 897 | #define SDRAM_CONFIG_PAGESIZE __BITS(2,0) |
898 | #endif | | 898 | #endif |
899 | | | 899 | |
| | | 900 | /* EDMA3 */ |
| | | 901 | #define AM335X_TPCC_BASE 0x49000000 |
| | | 902 | #define AM335X_TPCC_SIZE 0x00100000 |
| | | 903 | #define AM335X_TPTC0_BASE 0x49800000 |
| | | 904 | #define AM335X_TPTC0_SIZE 0x00100000 |
| | | 905 | #define AM335X_TPTC1_BASE 0x49900000 |
| | | 906 | #define AM335X_TPTC1_SIZE 0x00100000 |
| | | 907 | #define AM335X_TPTC2_BASE 0x49a00000 |
| | | 908 | #define AM335X_TPTC2_SIZE 0x00100000 |
| | | 909 | #define AM335X_INT_EDMACOMPINT 12 |
| | | 910 | #define AM335X_INT_EDMAMPERR 13 |
| | | 911 | #define AM335X_INT_EDMAERRINT 14 |
| | | 912 | #define AM335X_INT_TCERRINT0 112 |
| | | 913 | #define AM335X_INT_TCERRINT1 113 |
| | | 914 | #define AM335X_INT_TCERRINT2 114 |
900 | #endif /* _ARM_OMAP_OMAP2_REG_H_ */ | | 915 | #endif /* _ARM_OMAP_OMAP2_REG_H_ */ |
/* $NetBSD: omap_edma.c,v 1.1 2015/04/14 18:37:43 bouyer Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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>
__KERNEL_RCSID(0, "$NetBSD: omap_edma.c,v 1.1 2015/04/14 18:37:43 bouyer Exp $");
#include "opt_omap.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/intr.h>
#include <sys/mutex.h>
#include <sys/bus.h>
#include <sys/bitops.h>
#include <arm/omap/am335x_prcm.h>
#include <arm/omap/omap2_prcm.h>
#include <arm/omap/sitara_cm.h>
#include <arm/omap/sitara_cmreg.h>
#include <arm/omap/omap2_reg.h>
#include <arm/omap/omap2_obiovar.h>
#include <arm/omap/omap_edma.h>
#ifdef TI_AM335X
static const struct omap_module edma3cc_module =
{ AM335X_PRCM_CM_PER, CM_PER_TPCC_CLKCTRL };
static const struct omap_module edma3tc0_module =
{ AM335X_PRCM_CM_PER, CM_PER_TPTC0_CLKCTRL };
static const struct omap_module edma3tc1_module =
{ AM335X_PRCM_CM_PER, CM_PER_TPTC1_CLKCTRL };
static const struct omap_module edma3tc2_module =
{ AM335X_PRCM_CM_PER, CM_PER_TPTC2_CLKCTRL };
#endif
#define NUM_DMA_CHANNELS 64
#define NUM_PARAM_SETS 256
#define MAX_PARAM_PER_CHANNEL 32
#ifdef EDMA_DEBUG
int edmadebug = 1;
#define DPRINTF(n,s) do { if ((n) <= edmadebug) device_printf s; } while (0)
#else
#define DPRINTF(n,s) do {} while (0)
#endif
struct edma_softc;
struct edma_channel {
struct edma_softc *ch_sc;
enum edma_type ch_type;
uint8_t ch_index;
void (*ch_callback)(void *);
void *ch_callbackarg;
unsigned int ch_nparams;
};
struct edma_softc {
device_t sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
kmutex_t sc_lock;
struct edma_channel sc_dma[NUM_DMA_CHANNELS];
void *sc_ih;
void *sc_mperr_ih;
void *sc_errint_ih;
uint32_t sc_dmamask[NUM_DMA_CHANNELS / 32];
uint32_t sc_parammask[NUM_PARAM_SETS / 32];
};
static int edma_match(device_t, cfdata_t, void *);
static void edma_attach(device_t, device_t, void *);
static void edma_init(struct edma_softc *);
static int edma_intr(void *);
static int edma_mperr_intr(void *);
static int edma_errint_intr(void *);
static void edma_write_param(struct edma_softc *,
unsigned int, const struct edma_param *);
static bool edma_bit_isset(uint32_t *, unsigned int);
static void edma_bit_set(uint32_t *, unsigned int);
static void edma_bit_clr(uint32_t *, unsigned int);
CFATTACH_DECL_NEW(edma, sizeof(struct edma_softc),
edma_match, edma_attach, NULL, NULL);
#define EDMA_READ(sc, reg) \
bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
#define EDMA_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
static int
edma_match(device_t parent, cfdata_t match, void *aux)
{
struct obio_attach_args *obio = aux;
#ifdef TI_AM335X
if (obio->obio_addr == AM335X_TPCC_BASE &&
obio->obio_size == AM335X_TPCC_SIZE &&
obio->obio_intrbase == AM335X_INT_EDMACOMPINT)
return 1;
#endif
return 0;
}
static void
edma_attach(device_t parent, device_t self, void *aux)
{
struct edma_softc *sc = device_private(self);
struct obio_attach_args *obio = aux;
int idx;
sc->sc_dev = self;
sc->sc_iot = obio->obio_iot;
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size,
0, &sc->sc_ioh) != 0) {
aprint_error(": couldn't map address spcae\n");
return;
}
aprint_normal("\n");
aprint_naive("\n");
for (idx = 0; idx < NUM_DMA_CHANNELS; idx++) {
struct edma_channel *ch = &sc->sc_dma[idx];
ch->ch_sc = sc;
ch->ch_type = EDMA_TYPE_DMA;
ch->ch_index = idx;
ch->ch_callback = NULL;
ch->ch_callbackarg = NULL;
ch->ch_nparams = 0;
}
edma_init(sc);
sc->sc_ih = intr_establish(obio->obio_intrbase + 0,
IPL_SCHED, IST_LEVEL, edma_intr, sc);
KASSERT(sc->sc_ih != NULL);
sc->sc_mperr_ih = intr_establish(obio->obio_intrbase + 1,
IPL_SCHED, IST_LEVEL, edma_mperr_intr, sc);
sc->sc_errint_ih = intr_establish(obio->obio_intrbase + 2,
IPL_SCHED, IST_LEVEL, edma_errint_intr, sc);
}
/*
* Hardware initialization
*/
static void
edma_init(struct edma_softc *sc)
{
struct edma_param param;
uint32_t val;
int idx;
#ifdef TI_AM335X
prcm_module_enable(&edma3cc_module);
prcm_module_enable(&edma3tc0_module);
prcm_module_enable(&edma3tc1_module);
prcm_module_enable(&edma3tc2_module);
#endif
val = EDMA_READ(sc, EDMA_CCCFG_REG);
if (val & EDMA_CCCFG_CHMAP_EXIST) {
for (idx = 0; idx < NUM_DMA_CHANNELS; idx++) {
EDMA_WRITE(sc, EDMA_DCHMAP_REG(idx),
__SHIFTIN(0, EDMA_DCHMAP_PAENTRY));
}
}
memset(¶m, 0, sizeof(param));
param.ep_bcnt = 1;
for (idx = 0; idx < NUM_PARAM_SETS; idx++) {
edma_write_param(sc, idx, ¶m);
}
/* reserve PaRAM entry 0 for dummy slot */
edma_bit_set(sc->sc_parammask, 0);
for (idx = 1; idx <= 32; idx++) {
edma_bit_set(sc->sc_parammask, idx);
}
}
/*
* Write a PaRAM entry
*/
static void
edma_write_param(struct edma_softc *sc,
unsigned int idx, const struct edma_param *ep)
{
EDMA_WRITE(sc, EDMA_PARAM_OPT_REG(idx), ep->ep_opt);
EDMA_WRITE(sc, EDMA_PARAM_SRC_REG(idx), ep->ep_src);
EDMA_WRITE(sc, EDMA_PARAM_CNT_REG(idx),
__SHIFTIN(ep->ep_bcnt, EDMA_PARAM_CNT_BCNT) |
__SHIFTIN(ep->ep_acnt, EDMA_PARAM_CNT_ACNT));
EDMA_WRITE(sc, EDMA_PARAM_DST_REG(idx), ep->ep_dst);
EDMA_WRITE(sc, EDMA_PARAM_BIDX_REG(idx),
__SHIFTIN(ep->ep_dstbidx, EDMA_PARAM_BIDX_DSTBIDX) |
__SHIFTIN(ep->ep_srcbidx, EDMA_PARAM_BIDX_SRCBIDX));
EDMA_WRITE(sc, EDMA_PARAM_LNK_REG(idx),
__SHIFTIN(ep->ep_bcntrld, EDMA_PARAM_LNK_BCNTRLD) |
__SHIFTIN(ep->ep_link, EDMA_PARAM_LNK_LINK));
EDMA_WRITE(sc, EDMA_PARAM_CIDX_REG(idx),
__SHIFTIN(ep->ep_dstcidx, EDMA_PARAM_CIDX_DSTCIDX) |
__SHIFTIN(ep->ep_srccidx, EDMA_PARAM_CIDX_SRCCIDX));
EDMA_WRITE(sc, EDMA_PARAM_CCNT_REG(idx),
__SHIFTIN(ep->ep_ccnt, EDMA_PARAM_CCNT_CCNT));
}
static bool
edma_bit_isset(uint32_t *bits, unsigned int bit)
{
return !!(bits[bit >> 5] & (1 << (bit & 0x1f)));
}
static void
edma_bit_set(uint32_t *bits, unsigned int bit)
{
bits[bit >> 5] |= (1 << (bit & 0x1f));
}
static void
edma_bit_clr(uint32_t *bits, unsigned int bit)
{
bits[bit >> 5] &= ~(1 << (bit & 0x1f));
}
static int
edma_intr(void *priv)
{
struct edma_softc *sc = priv;
uint64_t ipr, ier;
int bit, idx;
ipr = EDMA_READ(sc, EDMA_IPR_REG);
ipr |= (uint64_t)EDMA_READ(sc, EDMA_IPRH_REG) << 32;
if (ipr == 0)
return 0;
ier = EDMA_READ(sc, EDMA_IER_REG);
ier |= (uint64_t)EDMA_READ(sc, EDMA_IERH_REG) << 32;
DPRINTF(2, (sc->sc_dev, "ipr = 0x%016llx ier 0x%016llx\n", ipr, ier));
EDMA_WRITE(sc, EDMA_ICR_REG, ipr & 0xffffffff);
EDMA_WRITE(sc, EDMA_ICRH_REG, ipr >> 32);
while ((bit = ffs64(ipr)) != 0) {
idx = bit - 1;
ipr &= ~__BIT(idx);
if (!(ier & __BIT(idx)))
continue;
if (!edma_bit_isset(sc->sc_dmamask, idx))
continue;
sc->sc_dma[idx].ch_callback(sc->sc_dma[idx].ch_callbackarg);
}
EDMA_WRITE(sc, EDMA_IEVAL_REG, EDMA_IEVAL_EVAL);
return 1;
}
static int
edma_mperr_intr(void *priv)
{
printf(" ===== edma mperr!\n");
return 0;
}
static int
edma_errint_intr(void *priv)
{
printf(" ===== edma errint!\n");
return 0;
}
/*
* Allocate a DMA channel. Currently only DMA types are supported, not QDMA.
* Returns NULL on failure.
*/
struct edma_channel *
edma_channel_alloc(enum edma_type type, unsigned int drq,
void (*cb)(void *), void *cbarg)
{
struct edma_softc *sc;
device_t dev;
struct edma_channel *ch = NULL;
KASSERT(drq < __arraycount(sc->sc_dma));
KASSERT(type == EDMA_TYPE_DMA); /* QDMA not implemented */
KASSERT(cb != NULL);
KASSERT(cbarg != NULL);
dev = device_find_by_driver_unit("edma", 0);
if (dev == NULL)
return NULL;
sc = device_private(dev);
mutex_enter(&sc->sc_lock);
if (!edma_bit_isset(sc->sc_dmamask, drq)) {
ch = &sc->sc_dma[drq];
KASSERT(ch->ch_callback == NULL);
KASSERT(ch->ch_index == drq);
ch->ch_callback = cb;
ch->ch_callbackarg = cbarg;
edma_bit_set(sc->sc_dmamask, drq);
}
if (ch == NULL)
goto done;
EDMA_WRITE(sc, EDMA_DRAE_REG(0), sc->sc_dmamask[0]);
EDMA_WRITE(sc, EDMA_DRAEH_REG(0), sc->sc_dmamask[1]);
if (ch->ch_index < 32) {
EDMA_WRITE(sc, EDMA_ICR_REG, __BIT(ch->ch_index));
EDMA_WRITE(sc, EDMA_IESR_REG, __BIT(ch->ch_index));
} else {
EDMA_WRITE(sc, EDMA_ICRH_REG, __BIT(ch->ch_index - 32));
EDMA_WRITE(sc, EDMA_IESRH_REG, __BIT(ch->ch_index - 32));
}
done:
mutex_exit(&sc->sc_lock);
return ch;
}
/*
* Free a DMA channel allocated with edma_channel_alloc
*/
void
edma_channel_free(struct edma_channel *ch)
{
struct edma_softc *sc = ch->ch_sc;
KASSERT(ch->ch_nparams == 0);
mutex_enter(&sc->sc_lock);
if (ch->ch_index < 32) {
EDMA_WRITE(sc, EDMA_IECR_REG, __BIT(ch->ch_index));
} else {
EDMA_WRITE(sc, EDMA_IECRH_REG, __BIT(ch->ch_index - 32));
}
ch->ch_callback = NULL;
ch->ch_callbackarg = NULL;
edma_bit_clr(sc->sc_dmamask, ch->ch_index);
mutex_exit(&sc->sc_lock);
}
/*
* Allocate a PaRAM entry. The driver artifically restricts the number
* of PaRAM entries available for each channel to MAX_PARAM_PER_CHANNEL.
* If the number of entries for the channel has been exceeded, or there
* are no entries available, 0xffff is returned.
*/
uint16_t
edma_param_alloc(struct edma_channel *ch)
{
struct edma_softc *sc = ch->ch_sc;
uint16_t param_entry = 0xffff;
int idx;
if (ch->ch_nparams == MAX_PARAM_PER_CHANNEL)
return param_entry;
mutex_enter(&sc->sc_lock);
for (idx = 0; idx < NUM_PARAM_SETS; idx++) {
if (!edma_bit_isset(sc->sc_parammask, idx)) {
param_entry = idx;
edma_bit_set(sc->sc_parammask, idx);
ch->ch_nparams++;
break;
}
}
mutex_exit(&sc->sc_lock);
return param_entry;
}
/*
* Free a PaRAM entry allocated with edma_param_alloc
*/
void
edma_param_free(struct edma_channel *ch, uint16_t param_entry)
{
struct edma_softc *sc = ch->ch_sc;
KASSERT(param_entry < NUM_PARAM_SETS);
KASSERT(ch->ch_nparams > 0);
KASSERT(edma_bit_isset(sc->sc_parammask, param_entry));
mutex_enter(&sc->sc_lock);
edma_bit_clr(sc->sc_parammask, param_entry);
ch->ch_nparams--;
mutex_exit(&sc->sc_lock);
}
/*
* Update a PaRAM entry register set with caller-provided values
*/
void
edma_set_param(struct edma_channel *ch, uint16_t param_entry,
struct edma_param *ep)
{
struct edma_softc *sc = ch->ch_sc;
KASSERT(param_entry < NUM_PARAM_SETS);
KASSERT(ch->ch_nparams > 0);
KASSERT(edma_bit_isset(sc->sc_parammask, param_entry));
DPRINTF(1, (sc->sc_dev, "write param entry ch# %d pe %d: 0x%08x -> 0x%08x (%u, %u, %u)\n", ch->ch_index, param_entry, ep->ep_src, ep->ep_dst, ep->ep_acnt, ep->ep_bcnt, ep->ep_ccnt));
edma_write_param(sc, param_entry, ep);
}
/*
* Enable a DMA channel: Point channel to the PaRam entry,
* clear error if any, and only set the Event Enable bit.
* The Even will either be generated by hardware, or with
* edma_transfer_start()
*/
int
edma_transfer_enable(struct edma_channel *ch, uint16_t param_entry)
{
struct edma_softc *sc = ch->ch_sc;
bus_size_t off = (ch->ch_index < 32 ? 0 : 4);
uint32_t bit = __BIT(ch->ch_index < 32 ?
ch->ch_index : ch->ch_index - 32);
DPRINTF(1, (sc->sc_dev, "enable transfer ch# %d off %d bit %x pe %d\n", ch->ch_index, (int)off, bit, param_entry));
EDMA_WRITE(sc, EDMA_DCHMAP_REG(ch->ch_index),
__SHIFTIN(param_entry, EDMA_DCHMAP_PAENTRY));
uint32_t ccerr = EDMA_READ(sc, EDMA_CCERR_REG);
if (ccerr) {
device_printf(sc->sc_dev, " !!! CCER %08x\n", ccerr);
EDMA_WRITE(sc, EDMA_CCERRCLR_REG, ccerr);
}
EDMA_WRITE(sc, EDMA_EESR_REG + off, bit);
return 0;
}
/*
* Software-start a DMA channel: Set the Event bit.
*/
int
edma_transfer_start(struct edma_channel *ch)
{
struct edma_softc *sc = ch->ch_sc;
bus_size_t off = (ch->ch_index < 32 ? 0 : 4);
uint32_t bit = __BIT(ch->ch_index < 32 ?
ch->ch_index : ch->ch_index - 32);
DPRINTF(1, (sc->sc_dev, "start transfer ch# %d off %d bit %x pe %d\n", ch->ch_index, (int)off, bit));
EDMA_WRITE(sc, EDMA_ESR_REG + off, bit);
return 0;
}
/*
* Halt a DMA transfer. Called after successfull transfer, or to abort
* a transfer.
*/
void
edma_halt(struct edma_channel *ch)
{
struct edma_softc *sc = ch->ch_sc;
bus_size_t off = (ch->ch_index < 32 ? 0 : 4);
uint32_t bit = __BIT(ch->ch_index < 32 ?
ch->ch_index : ch->ch_index - 32);
EDMA_WRITE(sc, EDMA_EECR_REG + off, bit);
EDMA_WRITE(sc, EDMA_ECR_REG + off, bit);
EDMA_WRITE(sc, EDMA_SECR_REG + off, bit);
EDMA_WRITE(sc, EDMA_EMCR_REG + off, bit);
EDMA_WRITE(sc, EDMA_DCHMAP_REG(ch->ch_index),
__SHIFTIN(0, EDMA_DCHMAP_PAENTRY));
}
uint8_t
edma_channel_index(struct edma_channel *ch)
{
return ch->ch_index;
}
void
edma_dump(struct edma_channel *ch)
{
static const struct {
const char *name;
uint16_t off;
} regs[] = {
{ "ER", EDMA_ER_REG },
{ "ERH", EDMA_ERH_REG },
{ "EER", EDMA_EER_REG },
{ "EERH", EDMA_EERH_REG },
{ "SER", EDMA_SER_REG },
{ "SERH", EDMA_SERH_REG },
{ "IER", EDMA_IER_REG },
{ "IERH", EDMA_IERH_REG },
{ "IPR", EDMA_IPR_REG },
{ "IPRH", EDMA_IPRH_REG },
{ "CCERR", EDMA_CCERR_REG },
{ "CCSTAT", EDMA_CCSTAT_REG },
{ "DRAE0", EDMA_DRAE_REG(0) },
{ "DRAEH0", EDMA_DRAEH_REG(0) },
{ NULL, 0 }
};
struct edma_softc *sc = ch->ch_sc;
int i;
for (i = 0; regs[i].name; i++) {
device_printf(sc->sc_dev, "%s: %08x\n",
regs[i].name, EDMA_READ(sc, regs[i].off));
}
device_printf(sc->sc_dev, "DCHMAP%d: %08x\n", ch->ch_index,
EDMA_READ(sc, EDMA_DCHMAP_REG(ch->ch_index)));
}
void
edma_dump_param(struct edma_channel *ch, uint16_t param_entry)
{
struct {
const char *name;
uint16_t off;
} regs[] = {
{ "OPT", EDMA_PARAM_OPT_REG(param_entry) },
{ "CNT", EDMA_PARAM_CNT_REG(param_entry) },
{ "DST", EDMA_PARAM_DST_REG(param_entry) },
{ "BIDX", EDMA_PARAM_BIDX_REG(param_entry) },
{ "LNK", EDMA_PARAM_LNK_REG(param_entry) },
{ "CIDX", EDMA_PARAM_CIDX_REG(param_entry) },
{ "CCNT", EDMA_PARAM_CCNT_REG(param_entry) },
{ NULL, 0 }
};
struct edma_softc *sc = ch->ch_sc;
int i;
for (i = 0; regs[i].name; i++) {
device_printf(sc->sc_dev, "%s%d: %08x\n",
regs[i].name, param_entry, EDMA_READ(sc, regs[i].off));
}
}
/* $NetBSD: omap_edma.h,v 1.1 2015/04/14 18:37:43 bouyer Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 _OMAP_EDMA_H
#define _OMAP_EDMA_H
#define EDMA_PID_REG 0x0000
#define EDMA_CCCFG_REG 0x0004
#define EDMA_CCCFG_MP_EXIST __BIT(25)
#define EDMA_CCCFG_CHMAP_EXIST __BIT(24)
#define EDMA_CCCFG_NUM_REGN __BITS(21,20)
#define EDMA_CCCFG_NUM_EVQUEUE __BITS(18,16)
#define EDMA_CCCFG_NUM_PAENTRY __BITS(14,12)
#define EDMA_CCCFG_NUM_INTCH __BITS(10,8)
#define EDMA_CCCFG_NUM_QDMACH __BITS(6,4)
#define EDMA_CCCFG_NUM_DMACH __BITS(2,0)
#define EDMA_SYSCONFIG_REG 0x0010
#define EDMA_DCHMAP_REG(n) (0x0100 + 4 * (n))
#define EDMA_DCHMAP_PAENTRY __BITS(13,5)
#define EDMA_QCHMAP_REG(n) (0x0200 + 4 * (n))
#define EDMA_DMAQNUM_REG(n) (0x0240 + 4 * (n))
#define EDMA_QDMAQNUM_REG 0x0260
#define EDMA_QUEPRI_REG 0x0284
#define EDMA_EMR_REG 0x0300
#define EDMA_EMRH_REG 0x0304
#define EDMA_EMCR_REG 0x0308
#define EDMA_EMCRH_REG 0x030c
#define EDMA_QEMR_REG 0x0310
#define EDMA_QEMRC_REG 0x0314
#define EDMA_CCERR_REG 0x0318
#define EDMA_CCERRCLR_REG 0x031c
#define EDMA_EEVAL_REG 0x0320
#define EDMA_DRAE_REG(n) (0x0340 + 8 * (n))
#define EDMA_DRAEH_REG(n) (0x0340 + 8 * (n) + 4)
#define EDMA_QRAE_REG(n) (0x0380 + 4 * (n))
#define EDMA_QE_REG(q, e) (0x0400 + 0x40 * (q) + 4 * (e))
#define EDMA_QSTAT_REG(n) (0x0600 + 4 * (n))
#define EDMA_QWMTHRA_REG 0x0620
#define EDMA_CCSTAT_REG 0x0640
#define EDMA_MPFAR_REG 0x0800
#define EDMA_MPFSR_REG 0x0804
#define EDMA_MPFCR_REG 0x0808
#define EDMA_MPPAG_REG 0x080c
#define EDMA_MPPA_REG(n) (0x0810 + 4 * (n))
#define EDMA_ER_REG 0x1000
#define EDMA_ERH_REG 0x1004
#define EDMA_ECR_REG 0x1008
#define EDMA_ECRH_REG 0x100c
#define EDMA_ESR_REG 0x1010
#define EDMA_ESRH_REG 0x1014
#define EDMA_CER_REG 0x1018
#define EDMA_CERH_REG 0x101c
#define EDMA_EER_REG 0x1020
#define EDMA_EERH_REG 0x1024
#define EDMA_EECR_REG 0x1028
#define EDMA_EECRH_REG 0x102c
#define EDMA_EESR_REG 0x1030
#define EDMA_EESRH_REG 0x1034
#define EDMA_SER_REG 0x1038
#define EDMA_SERH_REG 0x103c
#define EDMA_SECR_REG 0x1040
#define EDMA_SECRH_REG 0x1044
#define EDMA_IER_REG 0x1050
#define EDMA_IERH_REG 0x1054
#define EDMA_IECR_REG 0x1058
#define EDMA_IECRH_REG 0x105c
#define EDMA_IESR_REG 0x1060
#define EDMA_IESRH_REG 0x1064
#define EDMA_IPR_REG 0x1068
#define EDMA_IPRH_REG 0x106c
#define EDMA_ICR_REG 0x1070
#define EDMA_ICRH_REG 0x1074
#define EDMA_IEVAL_REG 0x1078
#define EDMA_IEVAL_EVAL __BIT(0)
#define EDMA_QER_REG 0x1080
#define EDMA_QEER_REG 0x1084
#define EDMA_QEECR_REG 0x1088
#define EDMA_QEESR_REG 0x108c
#define EDMA_QSER_REG 0x1090
#define EDMA_QSECR_REG 0x1094
#define EDMA_PARAM_BASE(n) (0x4000 + 0x20 * (n))
#define EDMA_PARAM_OPT_REG(n) (EDMA_PARAM_BASE(n) + 0x00)
#define EDMA_PARAM_OPT_PRIV __BIT(31)
#define EDMA_PARAM_OPT_PRIVID __BITS(27,24)
#define EDMA_PARAM_OPT_ITCCHEN __BIT(23)
#define EDMA_PARAM_OPT_TCCHEN __BIT(22)
#define EDMA_PARAM_OPT_ITCINTEN __BIT(21)
#define EDMA_PARAM_OPT_TCINTEN __BIT(20)
#define EDMA_PARAM_OPT_TCC __BITS(17,12)
#define EDMA_PARAM_OPT_TCCMODE __BIT(11)
#define EDMA_PARAM_OPT_FWID __BITS(10,8)
#define EDMA_PARAM_OPT_STATIC __BIT(3)
#define EDMA_PARAM_OPT_SYNCDIM __BIT(2)
#define EDMA_PARAM_OPT_DAM __BIT(1)
#define EDMA_PARAM_OPT_SAM __BIT(0)
#define EDMA_PARAM_SRC_REG(n) (EDMA_PARAM_BASE(n) + 0x04)
#define EDMA_PARAM_CNT_REG(n) (EDMA_PARAM_BASE(n) + 0x08)
#define EDMA_PARAM_CNT_BCNT __BITS(31,16)
#define EDMA_PARAM_CNT_ACNT __BITS(15,0)
#define EDMA_PARAM_DST_REG(n) (EDMA_PARAM_BASE(n) + 0x0c)
#define EDMA_PARAM_BIDX_REG(n) (EDMA_PARAM_BASE(n) + 0x10)
#define EDMA_PARAM_BIDX_DSTBIDX __BITS(31,16)
#define EDMA_PARAM_BIDX_SRCBIDX __BITS(15,0)
#define EDMA_PARAM_LNK_REG(n) (EDMA_PARAM_BASE(n) + 0x14)
#define EDMA_PARAM_LNK_BCNTRLD __BITS(31,16)
#define EDMA_PARAM_LNK_LINK __BITS(15,0)
#define EDMA_PARAM_CIDX_REG(n) (EDMA_PARAM_BASE(n) + 0x18)
#define EDMA_PARAM_CIDX_DSTCIDX __BITS(31,16)
#define EDMA_PARAM_CIDX_SRCCIDX __BITS(15,0)
#define EDMA_PARAM_CCNT_REG(n) (EDMA_PARAM_BASE(n) + 0x1c)
#define EDMA_PARAM_CCNT_CCNT __BITS(15,0)
enum edma_type {
EDMA_TYPE_DMA,
EDMA_TYPE_QDMA
};
struct edma_param {
uint32_t ep_opt;
uint32_t ep_src;
uint32_t ep_dst;
uint16_t ep_bcnt;
uint16_t ep_acnt;
uint16_t ep_dstbidx;
uint16_t ep_srcbidx;
uint16_t ep_bcntrld;
uint16_t ep_link;
uint16_t ep_dstcidx;
uint16_t ep_srccidx;
uint16_t ep_ccnt;
};
struct edma_channel;
struct edma_channel *edma_channel_alloc(enum edma_type, unsigned int,
void (*)(void *), void *);
void edma_channel_free(struct edma_channel *);
uint16_t edma_param_alloc(struct edma_channel *);
void edma_param_free(struct edma_channel *, uint16_t);
void edma_set_param(struct edma_channel *, uint16_t, struct edma_param *);
int edma_transfer_enable(struct edma_channel *, uint16_t);
int edma_transfer_start(struct edma_channel *);
void edma_halt(struct edma_channel *);
uint8_t edma_channel_index(struct edma_channel *);
void edma_dump(struct edma_channel *);
void edma_dump_param(struct edma_channel *, uint16_t);
#endif /* !_OMAP_EDMA_H */