1f3a72e40SRuslan Bukin /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3af3dc4a7SPedro F. Giffuni *
4f3a72e40SRuslan Bukin * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
5f3a72e40SRuslan Bukin * All rights reserved.
6f3a72e40SRuslan Bukin *
7f3a72e40SRuslan Bukin * Redistribution and use in source and binary forms, with or without
8f3a72e40SRuslan Bukin * modification, are permitted provided that the following conditions
9f3a72e40SRuslan Bukin * are met:
10f3a72e40SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
11f3a72e40SRuslan Bukin * notice, this list of conditions and the following disclaimer.
12f3a72e40SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
13f3a72e40SRuslan Bukin * notice, this list of conditions and the following disclaimer in the
14f3a72e40SRuslan Bukin * documentation and/or other materials provided with the distribution.
15f3a72e40SRuslan Bukin *
16f3a72e40SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17f3a72e40SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18f3a72e40SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19f3a72e40SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20f3a72e40SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21f3a72e40SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22f3a72e40SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23f3a72e40SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24f3a72e40SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25f3a72e40SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26f3a72e40SRuslan Bukin * SUCH DAMAGE.
27f3a72e40SRuslan Bukin */
28f3a72e40SRuslan Bukin
29f3a72e40SRuslan Bukin /*
30f3a72e40SRuslan Bukin * Vybrid Family Direct Memory Access Multiplexer (DMAMUX)
31f3a72e40SRuslan Bukin * Chapter 22, Vybrid Reference Manual, Rev. 5, 07/2013
32f3a72e40SRuslan Bukin */
33f3a72e40SRuslan Bukin
34f3a72e40SRuslan Bukin #include <sys/param.h>
35f3a72e40SRuslan Bukin #include <sys/systm.h>
36f3a72e40SRuslan Bukin #include <sys/bus.h>
37f3a72e40SRuslan Bukin #include <sys/kernel.h>
38f3a72e40SRuslan Bukin #include <sys/module.h>
39f3a72e40SRuslan Bukin #include <sys/malloc.h>
40f3a72e40SRuslan Bukin #include <sys/rman.h>
41f3a72e40SRuslan Bukin #include <sys/timeet.h>
42f3a72e40SRuslan Bukin #include <sys/timetc.h>
43f3a72e40SRuslan Bukin #include <sys/watchdog.h>
44f3a72e40SRuslan Bukin
45f3a72e40SRuslan Bukin #include <dev/ofw/openfirm.h>
46f3a72e40SRuslan Bukin #include <dev/ofw/ofw_bus.h>
47f3a72e40SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h>
48f3a72e40SRuslan Bukin
49f3a72e40SRuslan Bukin #include <machine/bus.h>
50f3a72e40SRuslan Bukin #include <machine/cpu.h>
51f3a72e40SRuslan Bukin #include <machine/intr.h>
52f3a72e40SRuslan Bukin
53f3a72e40SRuslan Bukin #include <arm/freescale/vybrid/vf_common.h>
54f3a72e40SRuslan Bukin #include <arm/freescale/vybrid/vf_dmamux.h>
55f3a72e40SRuslan Bukin
56f3a72e40SRuslan Bukin #define DMAMUX_CHCFG(n) (0x1 * n) /* Channels 0-15 Cfg Reg */
57f3a72e40SRuslan Bukin #define CHCFG_ENBL (1 << 7) /* Channel Enable */
58f3a72e40SRuslan Bukin #define CHCFG_TRIG (1 << 6) /* Channel Trigger Enable */
59f3a72e40SRuslan Bukin #define CHCFG_SOURCE_MASK 0x3f /* Channel Source (Slot) */
60f3a72e40SRuslan Bukin #define CHCFG_SOURCE_SHIFT 0
61f3a72e40SRuslan Bukin
62f3a72e40SRuslan Bukin struct dmamux_softc {
63f3a72e40SRuslan Bukin struct resource *res[4];
64f3a72e40SRuslan Bukin bus_space_tag_t bst[4];
65f3a72e40SRuslan Bukin bus_space_handle_t bsh[4];
66f3a72e40SRuslan Bukin };
67f3a72e40SRuslan Bukin
68f3a72e40SRuslan Bukin struct dmamux_softc *dmamux_sc;
69f3a72e40SRuslan Bukin
70f3a72e40SRuslan Bukin static struct resource_spec dmamux_spec[] = {
71f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* DMAMUX0 */
72f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* DMAMUX1 */
73f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* DMAMUX2 */
74f3a72e40SRuslan Bukin { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* DMAMUX3 */
75f3a72e40SRuslan Bukin { -1, 0 }
76f3a72e40SRuslan Bukin };
77f3a72e40SRuslan Bukin
78f3a72e40SRuslan Bukin static int
dmamux_probe(device_t dev)79f3a72e40SRuslan Bukin dmamux_probe(device_t dev)
80f3a72e40SRuslan Bukin {
81f3a72e40SRuslan Bukin
82f3a72e40SRuslan Bukin if (!ofw_bus_status_okay(dev))
83f3a72e40SRuslan Bukin return (ENXIO);
84f3a72e40SRuslan Bukin
85f3a72e40SRuslan Bukin if (!ofw_bus_is_compatible(dev, "fsl,mvf600-dmamux"))
86f3a72e40SRuslan Bukin return (ENXIO);
87f3a72e40SRuslan Bukin
88f3a72e40SRuslan Bukin device_set_desc(dev, "Vybrid Family Direct Memory Access Multiplexer");
89f3a72e40SRuslan Bukin return (BUS_PROBE_DEFAULT);
90f3a72e40SRuslan Bukin }
91f3a72e40SRuslan Bukin
92f3a72e40SRuslan Bukin int
dmamux_configure(int mux,int source,int channel,int enable)93f3a72e40SRuslan Bukin dmamux_configure(int mux, int source, int channel, int enable)
94f3a72e40SRuslan Bukin {
95f3a72e40SRuslan Bukin struct dmamux_softc *sc;
96f3a72e40SRuslan Bukin int reg;
97f3a72e40SRuslan Bukin
98f3a72e40SRuslan Bukin sc = dmamux_sc;
99f3a72e40SRuslan Bukin
100f3a72e40SRuslan Bukin MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), 0x0);
101f3a72e40SRuslan Bukin
102f3a72e40SRuslan Bukin reg = 0;
103f3a72e40SRuslan Bukin if (enable)
104f3a72e40SRuslan Bukin reg |= (CHCFG_ENBL);
105f3a72e40SRuslan Bukin
106f3a72e40SRuslan Bukin reg &= ~(CHCFG_SOURCE_MASK << CHCFG_SOURCE_SHIFT);
107f3a72e40SRuslan Bukin reg |= (source << CHCFG_SOURCE_SHIFT);
108f3a72e40SRuslan Bukin
109f3a72e40SRuslan Bukin MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), reg);
110f3a72e40SRuslan Bukin
111f3a72e40SRuslan Bukin return (0);
112f3a72e40SRuslan Bukin }
113f3a72e40SRuslan Bukin
114f3a72e40SRuslan Bukin static int
dmamux_attach(device_t dev)115f3a72e40SRuslan Bukin dmamux_attach(device_t dev)
116f3a72e40SRuslan Bukin {
117f3a72e40SRuslan Bukin struct dmamux_softc *sc;
118f3a72e40SRuslan Bukin int i;
119f3a72e40SRuslan Bukin
120f3a72e40SRuslan Bukin sc = device_get_softc(dev);
121f3a72e40SRuslan Bukin
122f3a72e40SRuslan Bukin if (bus_alloc_resources(dev, dmamux_spec, sc->res)) {
123f3a72e40SRuslan Bukin device_printf(dev, "could not allocate resources\n");
124f3a72e40SRuslan Bukin return (ENXIO);
125f3a72e40SRuslan Bukin }
126f3a72e40SRuslan Bukin
127f3a72e40SRuslan Bukin /* Memory interface */
128f3a72e40SRuslan Bukin for (i = 0; i < 4; i++) {
129f3a72e40SRuslan Bukin sc->bst[i] = rman_get_bustag(sc->res[i]);
130f3a72e40SRuslan Bukin sc->bsh[i] = rman_get_bushandle(sc->res[i]);
131f3a72e40SRuslan Bukin }
132f3a72e40SRuslan Bukin
133f3a72e40SRuslan Bukin dmamux_sc = sc;
134f3a72e40SRuslan Bukin
135f3a72e40SRuslan Bukin return (0);
136f3a72e40SRuslan Bukin }
137f3a72e40SRuslan Bukin
138f3a72e40SRuslan Bukin static device_method_t dmamux_methods[] = {
139f3a72e40SRuslan Bukin DEVMETHOD(device_probe, dmamux_probe),
140f3a72e40SRuslan Bukin DEVMETHOD(device_attach, dmamux_attach),
141f3a72e40SRuslan Bukin { 0, 0 }
142f3a72e40SRuslan Bukin };
143f3a72e40SRuslan Bukin
144f3a72e40SRuslan Bukin static driver_t dmamux_driver = {
145f3a72e40SRuslan Bukin "dmamux",
146f3a72e40SRuslan Bukin dmamux_methods,
147f3a72e40SRuslan Bukin sizeof(struct dmamux_softc),
148f3a72e40SRuslan Bukin };
149f3a72e40SRuslan Bukin
150ea538dabSJohn Baldwin DRIVER_MODULE(dmamux, simplebus, dmamux_driver, 0, 0);
151