xref: /freebsd/sys/arm/ti/ti_sdma.c (revision 255eff3b0d4d3dc1b170b48ef970e372dff1b825)
1e53470feSOleksandr Tymoshenko /*-
2e53470feSOleksandr Tymoshenko  * Copyright (c) 2011
3e53470feSOleksandr Tymoshenko  *	Ben Gray <ben.r.gray@gmail.com>.
4e53470feSOleksandr Tymoshenko  * All rights reserved.
5e53470feSOleksandr Tymoshenko  *
6e53470feSOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
7e53470feSOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
8e53470feSOleksandr Tymoshenko  * are met:
9e53470feSOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
10e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
11e53470feSOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
12e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
13e53470feSOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
14e53470feSOleksandr Tymoshenko  *
15e53470feSOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e53470feSOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e53470feSOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e53470feSOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19e53470feSOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e53470feSOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e53470feSOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e53470feSOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e53470feSOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e53470feSOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e53470feSOleksandr Tymoshenko  * SUCH DAMAGE.
26e53470feSOleksandr Tymoshenko  */
27e53470feSOleksandr Tymoshenko 
28e53470feSOleksandr Tymoshenko #include <sys/cdefs.h>
29e53470feSOleksandr Tymoshenko __FBSDID("$FreeBSD$");
30e53470feSOleksandr Tymoshenko 
31e53470feSOleksandr Tymoshenko #include <sys/param.h>
32e53470feSOleksandr Tymoshenko #include <sys/systm.h>
33e53470feSOleksandr Tymoshenko #include <sys/bus.h>
34e53470feSOleksandr Tymoshenko #include <sys/kernel.h>
35e53470feSOleksandr Tymoshenko #include <sys/lock.h>
36e53470feSOleksandr Tymoshenko #include <sys/interrupt.h>
37e53470feSOleksandr Tymoshenko #include <sys/module.h>
38e53470feSOleksandr Tymoshenko #include <sys/malloc.h>
39e53470feSOleksandr Tymoshenko #include <sys/mutex.h>
40e53470feSOleksandr Tymoshenko #include <sys/rman.h>
41e53470feSOleksandr Tymoshenko #include <sys/queue.h>
42e53470feSOleksandr Tymoshenko #include <sys/taskqueue.h>
43e53470feSOleksandr Tymoshenko #include <sys/timetc.h>
44e53470feSOleksandr Tymoshenko #include <machine/bus.h>
45e53470feSOleksandr Tymoshenko #include <machine/intr.h>
46e53470feSOleksandr Tymoshenko 
47e53470feSOleksandr Tymoshenko #include <dev/fdt/fdt_common.h>
48e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h>
49e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
50e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
51e53470feSOleksandr Tymoshenko 
52e53470feSOleksandr Tymoshenko #include <arm/ti/ti_cpuid.h>
53e53470feSOleksandr Tymoshenko #include <arm/ti/ti_prcm.h>
54e53470feSOleksandr Tymoshenko #include <arm/ti/ti_sdma.h>
55e53470feSOleksandr Tymoshenko #include <arm/ti/ti_sdmareg.h>
56e53470feSOleksandr Tymoshenko 
57e53470feSOleksandr Tymoshenko /**
58e53470feSOleksandr Tymoshenko  *	Kernel functions for using the DMA controller
59e53470feSOleksandr Tymoshenko  *
60e53470feSOleksandr Tymoshenko  *
61e53470feSOleksandr Tymoshenko  *	DMA TRANSFERS:
62e53470feSOleksandr Tymoshenko  *	A DMA transfer block consists of a number of frames (FN). Each frame
63e53470feSOleksandr Tymoshenko  *	consists of a number of elements, and each element can have a size of 8, 16,
64e53470feSOleksandr Tymoshenko  *	or 32 bits.
65e53470feSOleksandr Tymoshenko  *
66e53470feSOleksandr Tymoshenko  *	OMAP44xx and newer chips support linked list (aka scatter gather) transfers,
67e53470feSOleksandr Tymoshenko  *	where a linked list of source/destination pairs can be placed in memory
68e53470feSOleksandr Tymoshenko  *	for the H/W to process.  Earlier chips only allowed you to chain multiple
69e53470feSOleksandr Tymoshenko  *	channels together.  However currently this linked list feature is not
70e53470feSOleksandr Tymoshenko  *	supported by the driver.
71e53470feSOleksandr Tymoshenko  *
72e53470feSOleksandr Tymoshenko  */
73e53470feSOleksandr Tymoshenko 
74e53470feSOleksandr Tymoshenko /**
75e53470feSOleksandr Tymoshenko  *	Data structure per DMA channel.
76e53470feSOleksandr Tymoshenko  *
77e53470feSOleksandr Tymoshenko  *
78e53470feSOleksandr Tymoshenko  */
79e53470feSOleksandr Tymoshenko struct ti_sdma_channel {
80e53470feSOleksandr Tymoshenko 
81e53470feSOleksandr Tymoshenko 	/*
82e53470feSOleksandr Tymoshenko 	 * The configuration registers for the given channel, these are modified
83e53470feSOleksandr Tymoshenko 	 * by the set functions and only written to the actual registers when a
84e53470feSOleksandr Tymoshenko 	 * transaction is started.
85e53470feSOleksandr Tymoshenko 	 */
86e53470feSOleksandr Tymoshenko 	uint32_t		reg_csdp;
87e53470feSOleksandr Tymoshenko 	uint32_t		reg_ccr;
88e53470feSOleksandr Tymoshenko 	uint32_t		reg_cicr;
89e53470feSOleksandr Tymoshenko 
90e53470feSOleksandr Tymoshenko 	/* Set when one of the configuration registers above change */
91e53470feSOleksandr Tymoshenko 	uint32_t		need_reg_write;
92e53470feSOleksandr Tymoshenko 
93e53470feSOleksandr Tymoshenko 	/* Callback function used when an interrupt is tripped on the given channel */
94e53470feSOleksandr Tymoshenko 	void (*callback)(unsigned int ch, uint32_t ch_status, void *data);
95e53470feSOleksandr Tymoshenko 
96e53470feSOleksandr Tymoshenko 	/* Callback data passed in the callback ... duh */
97e53470feSOleksandr Tymoshenko 	void*			callback_data;
98e53470feSOleksandr Tymoshenko 
99e53470feSOleksandr Tymoshenko };
100e53470feSOleksandr Tymoshenko 
101e53470feSOleksandr Tymoshenko /**
102e53470feSOleksandr Tymoshenko  *	DMA driver context, allocated and stored globally, this driver is not
103e53470feSOleksandr Tymoshenko  *	intetned to ever be unloaded (see ti_sdma_sc).
104e53470feSOleksandr Tymoshenko  *
105e53470feSOleksandr Tymoshenko  */
106e53470feSOleksandr Tymoshenko struct ti_sdma_softc {
107e53470feSOleksandr Tymoshenko 	device_t		sc_dev;
108e53470feSOleksandr Tymoshenko 	struct resource*	sc_irq_res;
109e53470feSOleksandr Tymoshenko 	struct resource*	sc_mem_res;
110e53470feSOleksandr Tymoshenko 
111e53470feSOleksandr Tymoshenko 	/*
112e53470feSOleksandr Tymoshenko 	 * I guess in theory we should have a mutex per DMA channel for register
113e53470feSOleksandr Tymoshenko 	 * modifications. But since we know we are never going to be run on a SMP
114e53470feSOleksandr Tymoshenko 	 * system, we can use just the single lock for all channels.
115e53470feSOleksandr Tymoshenko 	 */
116e53470feSOleksandr Tymoshenko 	struct mtx		sc_mtx;
117e53470feSOleksandr Tymoshenko 
118e53470feSOleksandr Tymoshenko 	/* Stores the H/W revision read from the registers */
119e53470feSOleksandr Tymoshenko 	uint32_t		sc_hw_rev;
120e53470feSOleksandr Tymoshenko 
121e53470feSOleksandr Tymoshenko 	/*
122e53470feSOleksandr Tymoshenko 	 * Bits in the sc_active_channels data field indicate if the channel has
123e53470feSOleksandr Tymoshenko 	 * been activated.
124e53470feSOleksandr Tymoshenko 	 */
125e53470feSOleksandr Tymoshenko 	uint32_t		sc_active_channels;
126e53470feSOleksandr Tymoshenko 
127e53470feSOleksandr Tymoshenko 	struct ti_sdma_channel sc_channel[NUM_DMA_CHANNELS];
128e53470feSOleksandr Tymoshenko 
129e53470feSOleksandr Tymoshenko };
130e53470feSOleksandr Tymoshenko 
131e53470feSOleksandr Tymoshenko static struct ti_sdma_softc *ti_sdma_sc = NULL;
132e53470feSOleksandr Tymoshenko 
133e53470feSOleksandr Tymoshenko /**
134e53470feSOleksandr Tymoshenko  *	Macros for driver mutex locking
135e53470feSOleksandr Tymoshenko  */
136e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK(_sc)             mtx_lock_spin(&(_sc)->sc_mtx)
137e53470feSOleksandr Tymoshenko #define TI_SDMA_UNLOCK(_sc)           mtx_unlock_spin(&(_sc)->sc_mtx)
138e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK_INIT(_sc) \
139e53470feSOleksandr Tymoshenko 	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
140e53470feSOleksandr Tymoshenko 	         "ti_sdma", MTX_SPIN)
141e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK_DESTROY(_sc)     mtx_destroy(&_sc->sc_mtx);
142e53470feSOleksandr Tymoshenko #define TI_SDMA_ASSERT_LOCKED(_sc)    mtx_assert(&_sc->sc_mtx, MA_OWNED);
143e53470feSOleksandr Tymoshenko #define TI_SDMA_ASSERT_UNLOCKED(_sc)  mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
144e53470feSOleksandr Tymoshenko 
145e53470feSOleksandr Tymoshenko /**
146e53470feSOleksandr Tymoshenko  *	Function prototypes
147e53470feSOleksandr Tymoshenko  *
148e53470feSOleksandr Tymoshenko  */
149e53470feSOleksandr Tymoshenko static void ti_sdma_intr(void *);
150e53470feSOleksandr Tymoshenko 
151e53470feSOleksandr Tymoshenko /**
152e53470feSOleksandr Tymoshenko  *	ti_sdma_read_4 - reads a 32-bit value from one of the DMA registers
153e53470feSOleksandr Tymoshenko  *	@sc: DMA device context
154e53470feSOleksandr Tymoshenko  *	@off: The offset of a register from the DMA register address range
155e53470feSOleksandr Tymoshenko  *
156e53470feSOleksandr Tymoshenko  *
157e53470feSOleksandr Tymoshenko  *	RETURNS:
158e53470feSOleksandr Tymoshenko  *	32-bit value read from the register.
159e53470feSOleksandr Tymoshenko  */
160e53470feSOleksandr Tymoshenko static inline uint32_t
161e53470feSOleksandr Tymoshenko ti_sdma_read_4(struct ti_sdma_softc *sc, bus_size_t off)
162e53470feSOleksandr Tymoshenko {
163e53470feSOleksandr Tymoshenko 	return bus_read_4(sc->sc_mem_res, off);
164e53470feSOleksandr Tymoshenko }
165e53470feSOleksandr Tymoshenko 
166e53470feSOleksandr Tymoshenko /**
167e53470feSOleksandr Tymoshenko  *	ti_sdma_write_4 - writes a 32-bit value to one of the DMA registers
168e53470feSOleksandr Tymoshenko  *	@sc: DMA device context
169e53470feSOleksandr Tymoshenko  *	@off: The offset of a register from the DMA register address range
170e53470feSOleksandr Tymoshenko  *
171e53470feSOleksandr Tymoshenko  *
172e53470feSOleksandr Tymoshenko  *	RETURNS:
173e53470feSOleksandr Tymoshenko  *	32-bit value read from the register.
174e53470feSOleksandr Tymoshenko  */
175e53470feSOleksandr Tymoshenko static inline void
176e53470feSOleksandr Tymoshenko ti_sdma_write_4(struct ti_sdma_softc *sc, bus_size_t off, uint32_t val)
177e53470feSOleksandr Tymoshenko {
178e53470feSOleksandr Tymoshenko 	bus_write_4(sc->sc_mem_res, off, val);
179e53470feSOleksandr Tymoshenko }
180e53470feSOleksandr Tymoshenko 
181e53470feSOleksandr Tymoshenko /**
182e53470feSOleksandr Tymoshenko  *	ti_sdma_is_omap3_rev - returns true if H/W is from OMAP3 series
183e53470feSOleksandr Tymoshenko  *	@sc: DMA device context
184e53470feSOleksandr Tymoshenko  *
185e53470feSOleksandr Tymoshenko  */
186e53470feSOleksandr Tymoshenko static inline int
187e53470feSOleksandr Tymoshenko ti_sdma_is_omap3_rev(struct ti_sdma_softc *sc)
188e53470feSOleksandr Tymoshenko {
189e53470feSOleksandr Tymoshenko 	return (sc->sc_hw_rev == DMA4_OMAP3_REV);
190e53470feSOleksandr Tymoshenko }
191e53470feSOleksandr Tymoshenko 
192e53470feSOleksandr Tymoshenko /**
193e53470feSOleksandr Tymoshenko  *	ti_sdma_is_omap4_rev - returns true if H/W is from OMAP4 series
194e53470feSOleksandr Tymoshenko  *	@sc: DMA device context
195e53470feSOleksandr Tymoshenko  *
196e53470feSOleksandr Tymoshenko  */
197e53470feSOleksandr Tymoshenko static inline int
198e53470feSOleksandr Tymoshenko ti_sdma_is_omap4_rev(struct ti_sdma_softc *sc)
199e53470feSOleksandr Tymoshenko {
200e53470feSOleksandr Tymoshenko 	return (sc->sc_hw_rev == DMA4_OMAP4_REV);
201e53470feSOleksandr Tymoshenko }
202e53470feSOleksandr Tymoshenko 
203e53470feSOleksandr Tymoshenko /**
204e53470feSOleksandr Tymoshenko  *	ti_sdma_intr - interrupt handler for all 4 DMA IRQs
205e53470feSOleksandr Tymoshenko  *	@arg: ignored
206e53470feSOleksandr Tymoshenko  *
207e53470feSOleksandr Tymoshenko  *	Called when any of the four DMA IRQs are triggered.
208e53470feSOleksandr Tymoshenko  *
209e53470feSOleksandr Tymoshenko  *	LOCKING:
210e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
211e53470feSOleksandr Tymoshenko  *
212e53470feSOleksandr Tymoshenko  *	RETURNS:
213e53470feSOleksandr Tymoshenko  *	nothing
214e53470feSOleksandr Tymoshenko  */
215e53470feSOleksandr Tymoshenko static void
216e53470feSOleksandr Tymoshenko ti_sdma_intr(void *arg)
217e53470feSOleksandr Tymoshenko {
218e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
219e53470feSOleksandr Tymoshenko 	uint32_t intr;
220e53470feSOleksandr Tymoshenko 	uint32_t csr;
221e53470feSOleksandr Tymoshenko 	unsigned int ch, j;
222e53470feSOleksandr Tymoshenko 	struct ti_sdma_channel* channel;
223e53470feSOleksandr Tymoshenko 
224e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
225e53470feSOleksandr Tymoshenko 
226e53470feSOleksandr Tymoshenko 	for (j = 0; j < NUM_DMA_IRQS; j++) {
227e53470feSOleksandr Tymoshenko 
228e53470feSOleksandr Tymoshenko 		/* Get the flag interrupts (enabled) */
229e53470feSOleksandr Tymoshenko 		intr = ti_sdma_read_4(sc, DMA4_IRQSTATUS_L(j));
230e53470feSOleksandr Tymoshenko 		intr &= ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
231e53470feSOleksandr Tymoshenko 		if (intr == 0x00000000)
232e53470feSOleksandr Tymoshenko 			continue;
233e53470feSOleksandr Tymoshenko 
234e53470feSOleksandr Tymoshenko 		/* Loop through checking the status bits */
235e53470feSOleksandr Tymoshenko 		for (ch = 0; ch < NUM_DMA_CHANNELS; ch++) {
236e53470feSOleksandr Tymoshenko 			if (intr & (1 << ch)) {
237e53470feSOleksandr Tymoshenko 				channel = &sc->sc_channel[ch];
238e53470feSOleksandr Tymoshenko 
239e53470feSOleksandr Tymoshenko 				/* Read the CSR regsiter and verify we don't have a spurious IRQ */
240e53470feSOleksandr Tymoshenko 				csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
241e53470feSOleksandr Tymoshenko 				if (csr == 0) {
242e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "Spurious DMA IRQ for channel "
243e53470feSOleksandr Tymoshenko 					              "%d\n", ch);
244e53470feSOleksandr Tymoshenko 					continue;
245e53470feSOleksandr Tymoshenko 				}
246e53470feSOleksandr Tymoshenko 
247e53470feSOleksandr Tymoshenko 				/* Sanity check this channel is active */
248e53470feSOleksandr Tymoshenko 				if ((sc->sc_active_channels & (1 << ch)) == 0) {
249e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "IRQ %d for a non-activated "
250e53470feSOleksandr Tymoshenko 					              "channel %d\n", j, ch);
251e53470feSOleksandr Tymoshenko 					continue;
252e53470feSOleksandr Tymoshenko 				}
253e53470feSOleksandr Tymoshenko 
254e53470feSOleksandr Tymoshenko 				/* Check the status error codes */
255e53470feSOleksandr Tymoshenko 				if (csr & DMA4_CSR_DROP)
256e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "Synchronization event drop "
257e53470feSOleksandr Tymoshenko 					              "occurred during the transfer on channel %u\n",
258e53470feSOleksandr Tymoshenko 								  ch);
259e53470feSOleksandr Tymoshenko 				if (csr & DMA4_CSR_SECURE_ERR)
260e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "Secure transaction error event "
261e53470feSOleksandr Tymoshenko 					              "on channel %u\n", ch);
262e53470feSOleksandr Tymoshenko 				if (csr & DMA4_CSR_MISALIGNED_ADRS_ERR)
263e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "Misaligned address error event "
264e53470feSOleksandr Tymoshenko 					              "on channel %u\n", ch);
265e53470feSOleksandr Tymoshenko 				if (csr & DMA4_CSR_TRANS_ERR) {
266e53470feSOleksandr Tymoshenko 					device_printf(sc->sc_dev, "Transaction error event on "
267e53470feSOleksandr Tymoshenko 					              "channel %u\n", ch);
268e53470feSOleksandr Tymoshenko 					/*
269e53470feSOleksandr Tymoshenko 					 * Apparently according to linux code, there is an errata
270e53470feSOleksandr Tymoshenko 					 * that says the channel is not disabled upon this error.
271e53470feSOleksandr Tymoshenko 					 * They explicitly disable the channel here .. since I
272e53470feSOleksandr Tymoshenko 					 * haven't seen the errata, I'm going to ignore for now.
273e53470feSOleksandr Tymoshenko 					 */
274e53470feSOleksandr Tymoshenko 				}
275e53470feSOleksandr Tymoshenko 
276e53470feSOleksandr Tymoshenko 				/* Clear the status flags for the IRQ */
277e53470feSOleksandr Tymoshenko 				ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
278e53470feSOleksandr Tymoshenko 				ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
279e53470feSOleksandr Tymoshenko 
280e53470feSOleksandr Tymoshenko 				/* Call the callback for the given channel */
281e53470feSOleksandr Tymoshenko 				if (channel->callback)
282e53470feSOleksandr Tymoshenko 					channel->callback(ch, csr, channel->callback_data);
283e53470feSOleksandr Tymoshenko 			}
284e53470feSOleksandr Tymoshenko 		}
285e53470feSOleksandr Tymoshenko 	}
286e53470feSOleksandr Tymoshenko 
287e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
288e53470feSOleksandr Tymoshenko 
289e53470feSOleksandr Tymoshenko 	return;
290e53470feSOleksandr Tymoshenko }
291e53470feSOleksandr Tymoshenko 
292e53470feSOleksandr Tymoshenko /**
293e53470feSOleksandr Tymoshenko  *	ti_sdma_activate_channel - activates a DMA channel
294e53470feSOleksandr Tymoshenko  *	@ch: upon return contains the channel allocated
295e53470feSOleksandr Tymoshenko  *	@callback: a callback function to associate with the channel
296e53470feSOleksandr Tymoshenko  *	@data: optional data supplied when the callback is called
297e53470feSOleksandr Tymoshenko  *
298e53470feSOleksandr Tymoshenko  *	Simply activates a channel be enabling and writing default values to the
299e53470feSOleksandr Tymoshenko  *	channel's register set.  It doesn't start a transaction, just populates the
300e53470feSOleksandr Tymoshenko  *	internal data structures and sets defaults.
301e53470feSOleksandr Tymoshenko  *
302e53470feSOleksandr Tymoshenko  *	Note this function doesn't enable interrupts, for that you need to call
303e53470feSOleksandr Tymoshenko  *	ti_sdma_enable_channel_irq(). If not using IRQ to detect the end of the
304e53470feSOleksandr Tymoshenko  *	transfer, you can use ti_sdma_status_poll() to detect a change in the
305e53470feSOleksandr Tymoshenko  *	status.
306e53470feSOleksandr Tymoshenko  *
307e53470feSOleksandr Tymoshenko  *	A channel must be activated before any of the other DMA functions can be
308e53470feSOleksandr Tymoshenko  *	called on it.
309e53470feSOleksandr Tymoshenko  *
310e53470feSOleksandr Tymoshenko  *	LOCKING:
311e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
312e53470feSOleksandr Tymoshenko  *
313e53470feSOleksandr Tymoshenko  *	RETURNS:
314e53470feSOleksandr Tymoshenko  *	0 on success, otherwise an error code
315e53470feSOleksandr Tymoshenko  */
316e53470feSOleksandr Tymoshenko int
317e53470feSOleksandr Tymoshenko ti_sdma_activate_channel(unsigned int *ch,
318e53470feSOleksandr Tymoshenko                           void (*callback)(unsigned int ch, uint32_t status, void *data),
319e53470feSOleksandr Tymoshenko                           void *data)
320e53470feSOleksandr Tymoshenko {
321e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
322e53470feSOleksandr Tymoshenko 	struct ti_sdma_channel *channel = NULL;
323e53470feSOleksandr Tymoshenko 	uint32_t addr;
324e53470feSOleksandr Tymoshenko 	unsigned int i;
325e53470feSOleksandr Tymoshenko 
326e53470feSOleksandr Tymoshenko 	/* Sanity check */
327e53470feSOleksandr Tymoshenko 	if (sc == NULL)
328e53470feSOleksandr Tymoshenko 		return (ENOMEM);
329e53470feSOleksandr Tymoshenko 
330e53470feSOleksandr Tymoshenko 	if (ch == NULL)
331e53470feSOleksandr Tymoshenko 		return (EINVAL);
332e53470feSOleksandr Tymoshenko 
333e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
334e53470feSOleksandr Tymoshenko 
335e53470feSOleksandr Tymoshenko 	/* Check to see if all channels are in use */
336e53470feSOleksandr Tymoshenko 	if (sc->sc_active_channels == 0xffffffff) {
337e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
338e53470feSOleksandr Tymoshenko 		return (ENOMEM);
339e53470feSOleksandr Tymoshenko 	}
340e53470feSOleksandr Tymoshenko 
341e53470feSOleksandr Tymoshenko 	/* Find the first non-active channel */
342e53470feSOleksandr Tymoshenko 	for (i = 0; i < NUM_DMA_CHANNELS; i++) {
343e53470feSOleksandr Tymoshenko 		if (!(sc->sc_active_channels & (0x1 << i))) {
344e53470feSOleksandr Tymoshenko 			sc->sc_active_channels |= (0x1 << i);
345e53470feSOleksandr Tymoshenko 			*ch = i;
346e53470feSOleksandr Tymoshenko 			break;
347e53470feSOleksandr Tymoshenko 		}
348e53470feSOleksandr Tymoshenko 	}
349e53470feSOleksandr Tymoshenko 
350e53470feSOleksandr Tymoshenko 	/* Get the channel struct and populate the fields */
351e53470feSOleksandr Tymoshenko 	channel = &sc->sc_channel[*ch];
352e53470feSOleksandr Tymoshenko 
353e53470feSOleksandr Tymoshenko 	channel->callback = callback;
354e53470feSOleksandr Tymoshenko 	channel->callback_data = data;
355e53470feSOleksandr Tymoshenko 
356e53470feSOleksandr Tymoshenko 	channel->need_reg_write = 1;
357e53470feSOleksandr Tymoshenko 
358e53470feSOleksandr Tymoshenko 	/* Set the default configuration for the DMA channel */
359e53470feSOleksandr Tymoshenko 	channel->reg_csdp = DMA4_CSDP_DATA_TYPE(0x2)
360e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_SRC_BURST_MODE(0)
361e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_DST_BURST_MODE(0)
362e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_SRC_ENDIANISM(0)
363e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_DST_ENDIANISM(0)
364e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_WRITE_MODE(0)
365e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_SRC_PACKED(0)
366e53470feSOleksandr Tymoshenko 		| DMA4_CSDP_DST_PACKED(0);
367e53470feSOleksandr Tymoshenko 
368e53470feSOleksandr Tymoshenko 	channel->reg_ccr = DMA4_CCR_DST_ADDRESS_MODE(1)
369e53470feSOleksandr Tymoshenko 		| DMA4_CCR_SRC_ADDRESS_MODE(1)
370e53470feSOleksandr Tymoshenko 		| DMA4_CCR_READ_PRIORITY(0)
371e53470feSOleksandr Tymoshenko 		| DMA4_CCR_WRITE_PRIORITY(0)
372e53470feSOleksandr Tymoshenko 		| DMA4_CCR_SYNC_TRIGGER(0)
373e53470feSOleksandr Tymoshenko 		| DMA4_CCR_FRAME_SYNC(0)
374e53470feSOleksandr Tymoshenko 		| DMA4_CCR_BLOCK_SYNC(0);
375e53470feSOleksandr Tymoshenko 
376e53470feSOleksandr Tymoshenko 	channel->reg_cicr = DMA4_CICR_TRANS_ERR_IE
377e53470feSOleksandr Tymoshenko 		| DMA4_CICR_SECURE_ERR_IE
378e53470feSOleksandr Tymoshenko 		| DMA4_CICR_SUPERVISOR_ERR_IE
379e53470feSOleksandr Tymoshenko 		| DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
380e53470feSOleksandr Tymoshenko 
381e53470feSOleksandr Tymoshenko 	/* Clear all the channel registers, this should abort any transaction */
382e53470feSOleksandr Tymoshenko 	for (addr = DMA4_CCR(*ch); addr <= DMA4_COLOR(*ch); addr += 4)
383e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, addr, 0x00000000);
384e53470feSOleksandr Tymoshenko 
385e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
386e53470feSOleksandr Tymoshenko 
387e53470feSOleksandr Tymoshenko 	return 0;
388e53470feSOleksandr Tymoshenko }
389e53470feSOleksandr Tymoshenko 
390e53470feSOleksandr Tymoshenko /**
391e53470feSOleksandr Tymoshenko  *	ti_sdma_deactivate_channel - deactivates a channel
392e53470feSOleksandr Tymoshenko  *	@ch: the channel to deactivate
393e53470feSOleksandr Tymoshenko  *
394e53470feSOleksandr Tymoshenko  *
395e53470feSOleksandr Tymoshenko  *
396e53470feSOleksandr Tymoshenko  *	LOCKING:
397e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
398e53470feSOleksandr Tymoshenko  *
399e53470feSOleksandr Tymoshenko  *	RETURNS:
400e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
401e53470feSOleksandr Tymoshenko  */
402e53470feSOleksandr Tymoshenko int
403e53470feSOleksandr Tymoshenko ti_sdma_deactivate_channel(unsigned int ch)
404e53470feSOleksandr Tymoshenko {
405e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
406e53470feSOleksandr Tymoshenko 	unsigned int j;
407e53470feSOleksandr Tymoshenko 	unsigned int addr;
408e53470feSOleksandr Tymoshenko 
409e53470feSOleksandr Tymoshenko 	/* Sanity check */
410e53470feSOleksandr Tymoshenko 	if (sc == NULL)
411e53470feSOleksandr Tymoshenko 		return (ENOMEM);
412e53470feSOleksandr Tymoshenko 
413e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
414e53470feSOleksandr Tymoshenko 
415e53470feSOleksandr Tymoshenko 	/* First check if the channel is currently active */
416e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
417e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
418e53470feSOleksandr Tymoshenko 		return (EBUSY);
419e53470feSOleksandr Tymoshenko 	}
420e53470feSOleksandr Tymoshenko 
421e53470feSOleksandr Tymoshenko 	/* Mark the channel as inactive */
422e53470feSOleksandr Tymoshenko 	sc->sc_active_channels &= ~(1 << ch);
423e53470feSOleksandr Tymoshenko 
424e53470feSOleksandr Tymoshenko 	/* Disable all DMA interrupts for the channel. */
425e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
426e53470feSOleksandr Tymoshenko 
427e53470feSOleksandr Tymoshenko 	/* Make sure the DMA transfer is stopped. */
428e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
429e53470feSOleksandr Tymoshenko 
430e53470feSOleksandr Tymoshenko 	/* Clear the CSR register and IRQ status register */
431e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
432e53470feSOleksandr Tymoshenko 	for (j = 0; j < NUM_DMA_IRQS; j++) {
433e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
434e53470feSOleksandr Tymoshenko 	}
435e53470feSOleksandr Tymoshenko 
436e53470feSOleksandr Tymoshenko 	/* Clear all the channel registers, this should abort any transaction */
437e53470feSOleksandr Tymoshenko 	for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4)
438e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, addr, 0x00000000);
439e53470feSOleksandr Tymoshenko 
440e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
441e53470feSOleksandr Tymoshenko 
442e53470feSOleksandr Tymoshenko 	return 0;
443e53470feSOleksandr Tymoshenko }
444e53470feSOleksandr Tymoshenko 
445e53470feSOleksandr Tymoshenko /**
446e53470feSOleksandr Tymoshenko  *	ti_sdma_disable_channel_irq - disables IRQ's on the given channel
447e53470feSOleksandr Tymoshenko  *	@ch: the channel to disable IRQ's on
448e53470feSOleksandr Tymoshenko  *
449*255eff3bSPedro F. Giffuni  *	Disable interrupt generation for the given channel.
450e53470feSOleksandr Tymoshenko  *
451e53470feSOleksandr Tymoshenko  *	LOCKING:
452e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
453e53470feSOleksandr Tymoshenko  *
454e53470feSOleksandr Tymoshenko  *	RETURNS:
455e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
456e53470feSOleksandr Tymoshenko  */
457e53470feSOleksandr Tymoshenko int
458e53470feSOleksandr Tymoshenko ti_sdma_disable_channel_irq(unsigned int ch)
459e53470feSOleksandr Tymoshenko {
460e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
461e53470feSOleksandr Tymoshenko 	uint32_t irq_enable;
462e53470feSOleksandr Tymoshenko 	unsigned int j;
463e53470feSOleksandr Tymoshenko 
464e53470feSOleksandr Tymoshenko 	/* Sanity check */
465e53470feSOleksandr Tymoshenko 	if (sc == NULL)
466e53470feSOleksandr Tymoshenko 		return (ENOMEM);
467e53470feSOleksandr Tymoshenko 
468e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
469e53470feSOleksandr Tymoshenko 
470e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
471e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
472e53470feSOleksandr Tymoshenko 		return (EINVAL);
473e53470feSOleksandr Tymoshenko 	}
474e53470feSOleksandr Tymoshenko 
475e53470feSOleksandr Tymoshenko 	/* Disable all the individual error conditions */
476e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_cicr = 0x0000;
477e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000);
478e53470feSOleksandr Tymoshenko 
479e53470feSOleksandr Tymoshenko 	/* Disable the channel interrupt enable */
480e53470feSOleksandr Tymoshenko 	for (j = 0; j < NUM_DMA_IRQS; j++) {
481e53470feSOleksandr Tymoshenko 		irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
482e53470feSOleksandr Tymoshenko 		irq_enable &= ~(1 << ch);
483e53470feSOleksandr Tymoshenko 
484e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable);
485e53470feSOleksandr Tymoshenko 	}
486e53470feSOleksandr Tymoshenko 
487e53470feSOleksandr Tymoshenko 	/* Indicate the registers need to be rewritten on the next transaction */
488e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
489e53470feSOleksandr Tymoshenko 
490e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
491e53470feSOleksandr Tymoshenko 
492e53470feSOleksandr Tymoshenko 	return (0);
493e53470feSOleksandr Tymoshenko }
494e53470feSOleksandr Tymoshenko 
495e53470feSOleksandr Tymoshenko /**
496e53470feSOleksandr Tymoshenko  *	ti_sdma_disable_channel_irq - enables IRQ's on the given channel
497e53470feSOleksandr Tymoshenko  *	@ch: the channel to enable IRQ's on
498e53470feSOleksandr Tymoshenko  *	@flags: bitmask of interrupt types to enable
499e53470feSOleksandr Tymoshenko  *
500e53470feSOleksandr Tymoshenko  *	Flags can be a bitmask of the following options:
501e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_DROP
502e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_HALF_FRAME_COMPL
503e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_FRAME_COMPL
504e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_START_LAST_FRAME
505e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_BLOCK_COMPL
506e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_ENDOF_PKT
507e53470feSOleksandr Tymoshenko  *		DMA_IRQ_FLAG_DRAIN
508e53470feSOleksandr Tymoshenko  *
509e53470feSOleksandr Tymoshenko  *
510e53470feSOleksandr Tymoshenko  *	LOCKING:
511e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
512e53470feSOleksandr Tymoshenko  *
513e53470feSOleksandr Tymoshenko  *	RETURNS:
514e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
515e53470feSOleksandr Tymoshenko  */
516e53470feSOleksandr Tymoshenko int
517e53470feSOleksandr Tymoshenko ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags)
518e53470feSOleksandr Tymoshenko {
519e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
520e53470feSOleksandr Tymoshenko 	uint32_t irq_enable;
521e53470feSOleksandr Tymoshenko 
522e53470feSOleksandr Tymoshenko 	/* Sanity check */
523e53470feSOleksandr Tymoshenko 	if (sc == NULL)
524e53470feSOleksandr Tymoshenko 		return (ENOMEM);
525e53470feSOleksandr Tymoshenko 
526e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
527e53470feSOleksandr Tymoshenko 
528e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
529e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
530e53470feSOleksandr Tymoshenko 		return (EINVAL);
531e53470feSOleksandr Tymoshenko 	}
532e53470feSOleksandr Tymoshenko 
533e53470feSOleksandr Tymoshenko 	/* Always enable the error interrupts if we have interrupts enabled */
534e53470feSOleksandr Tymoshenko 	flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE |
535e53470feSOleksandr Tymoshenko 	         DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
536e53470feSOleksandr Tymoshenko 
537e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_cicr = flags;
538e53470feSOleksandr Tymoshenko 
539e53470feSOleksandr Tymoshenko 	/* Write the values to the register */
540e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CICR(ch), flags);
541e53470feSOleksandr Tymoshenko 
542e53470feSOleksandr Tymoshenko 	/* Enable the channel interrupt enable */
543e53470feSOleksandr Tymoshenko 	irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0));
544e53470feSOleksandr Tymoshenko 	irq_enable |= (1 << ch);
545e53470feSOleksandr Tymoshenko 
546e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable);
547e53470feSOleksandr Tymoshenko 
548e53470feSOleksandr Tymoshenko 	/* Indicate the registers need to be rewritten on the next transaction */
549e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
550e53470feSOleksandr Tymoshenko 
551e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
552e53470feSOleksandr Tymoshenko 
553e53470feSOleksandr Tymoshenko 	return (0);
554e53470feSOleksandr Tymoshenko }
555e53470feSOleksandr Tymoshenko 
556e53470feSOleksandr Tymoshenko /**
557e53470feSOleksandr Tymoshenko  *	ti_sdma_get_channel_status - returns the status of a given channel
558e53470feSOleksandr Tymoshenko  *	@ch: the channel number to get the status of
559e53470feSOleksandr Tymoshenko  *	@status: upon return will contain the status bitmask, see below for possible
560e53470feSOleksandr Tymoshenko  *	         values.
561e53470feSOleksandr Tymoshenko  *
562e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_DROP
563e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_HALF
564e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_FRAME
565e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_LAST
566e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_BLOCK
567e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_SYNC
568e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_PKT
569e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_TRANS_ERR
570e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_SECURE_ERR
571e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_SUPERVISOR_ERR
572e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_MISALIGNED_ADRS_ERR
573e53470feSOleksandr Tymoshenko  *	      DMA_STATUS_DRAIN_END
574e53470feSOleksandr Tymoshenko  *
575e53470feSOleksandr Tymoshenko  *
576e53470feSOleksandr Tymoshenko  *	LOCKING:
577e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
578e53470feSOleksandr Tymoshenko  *
579e53470feSOleksandr Tymoshenko  *	RETURNS:
580e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
581e53470feSOleksandr Tymoshenko  */
582e53470feSOleksandr Tymoshenko int
583e53470feSOleksandr Tymoshenko ti_sdma_get_channel_status(unsigned int ch, uint32_t *status)
584e53470feSOleksandr Tymoshenko {
585e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
586e53470feSOleksandr Tymoshenko 	uint32_t csr;
587e53470feSOleksandr Tymoshenko 
588e53470feSOleksandr Tymoshenko 	/* Sanity check */
589e53470feSOleksandr Tymoshenko 	if (sc == NULL)
590e53470feSOleksandr Tymoshenko 		return (ENOMEM);
591e53470feSOleksandr Tymoshenko 
592e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
593e53470feSOleksandr Tymoshenko 
594e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
595e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
596e53470feSOleksandr Tymoshenko 		return (EINVAL);
597e53470feSOleksandr Tymoshenko 	}
598e53470feSOleksandr Tymoshenko 
599e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
600e53470feSOleksandr Tymoshenko 
601e53470feSOleksandr Tymoshenko 	csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
602e53470feSOleksandr Tymoshenko 
603e53470feSOleksandr Tymoshenko 	if (status != NULL)
604e53470feSOleksandr Tymoshenko 		*status = csr;
605e53470feSOleksandr Tymoshenko 
606e53470feSOleksandr Tymoshenko 	return (0);
607e53470feSOleksandr Tymoshenko }
608e53470feSOleksandr Tymoshenko 
609e53470feSOleksandr Tymoshenko /**
610e53470feSOleksandr Tymoshenko  *	ti_sdma_start_xfer - starts a DMA transfer
611*255eff3bSPedro F. Giffuni  *	@ch: the channel number to set the endianness of
612e53470feSOleksandr Tymoshenko  *	@src_paddr: the source phsyical address
613e53470feSOleksandr Tymoshenko  *	@dst_paddr: the destination phsyical address
614e53470feSOleksandr Tymoshenko  *	@frmcnt: the number of frames per block
615e53470feSOleksandr Tymoshenko  *	@elmcnt: the number of elements in a frame, an element is either an 8, 16
616e53470feSOleksandr Tymoshenko  *           or 32-bit value as defined by ti_sdma_set_xfer_burst()
617e53470feSOleksandr Tymoshenko  *
618e53470feSOleksandr Tymoshenko  *
619e53470feSOleksandr Tymoshenko  *	LOCKING:
620e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
621e53470feSOleksandr Tymoshenko  *
622e53470feSOleksandr Tymoshenko  *	RETURNS:
623e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
624e53470feSOleksandr Tymoshenko  */
625e53470feSOleksandr Tymoshenko int
626e53470feSOleksandr Tymoshenko ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr,
627e53470feSOleksandr Tymoshenko                     unsigned long dst_paddr,
628e53470feSOleksandr Tymoshenko                     unsigned int frmcnt, unsigned int elmcnt)
629e53470feSOleksandr Tymoshenko {
630e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
631e53470feSOleksandr Tymoshenko 	struct ti_sdma_channel *channel;
632e53470feSOleksandr Tymoshenko 	uint32_t ccr;
633e53470feSOleksandr Tymoshenko 
634e53470feSOleksandr Tymoshenko 	/* Sanity check */
635e53470feSOleksandr Tymoshenko 	if (sc == NULL)
636e53470feSOleksandr Tymoshenko 		return (ENOMEM);
637e53470feSOleksandr Tymoshenko 
638e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
639e53470feSOleksandr Tymoshenko 
640e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
641e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
642e53470feSOleksandr Tymoshenko 		return (EINVAL);
643e53470feSOleksandr Tymoshenko 	}
644e53470feSOleksandr Tymoshenko 
645e53470feSOleksandr Tymoshenko 	channel = &sc->sc_channel[ch];
646e53470feSOleksandr Tymoshenko 
647e53470feSOleksandr Tymoshenko 	/* a) Write the CSDP register */
648e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSDP(ch),
649e53470feSOleksandr Tymoshenko 	    channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
650e53470feSOleksandr Tymoshenko 
651e53470feSOleksandr Tymoshenko 	/* b) Set the number of element per frame CEN[23:0] */
652e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
653e53470feSOleksandr Tymoshenko 
654e53470feSOleksandr Tymoshenko 	/* c) Set the number of frame per block CFN[15:0] */
655e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
656e53470feSOleksandr Tymoshenko 
657e53470feSOleksandr Tymoshenko 	/* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */
658e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
659e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
660e53470feSOleksandr Tymoshenko 
661e53470feSOleksandr Tymoshenko 	/* e) Write the CCR register */
662e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch), channel->reg_ccr);
663e53470feSOleksandr Tymoshenko 
664e53470feSOleksandr Tymoshenko 	/* f)  - Set the source element index increment CSEI[15:0] */
665e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
666e53470feSOleksandr Tymoshenko 
667e53470feSOleksandr Tymoshenko 	/*     - Set the source frame index increment CSFI[15:0] */
668e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSF(ch), 0x0001);
669e53470feSOleksandr Tymoshenko 
670e53470feSOleksandr Tymoshenko 	/*     - Set the destination element index increment CDEI[15:0]*/
671e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
672e53470feSOleksandr Tymoshenko 
673e53470feSOleksandr Tymoshenko 	/* - Set the destination frame index increment CDFI[31:0] */
674e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CDF(ch), 0x0001);
675e53470feSOleksandr Tymoshenko 
676e53470feSOleksandr Tymoshenko 	/* Clear the status register */
677e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
678e53470feSOleksandr Tymoshenko 
679e53470feSOleksandr Tymoshenko 	/* Write the start-bit and away we go */
680e53470feSOleksandr Tymoshenko 	ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
681e53470feSOleksandr Tymoshenko 	ccr |= (1 << 7);
682e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
683e53470feSOleksandr Tymoshenko 
684e53470feSOleksandr Tymoshenko 	/* Clear the reg write flag */
685e53470feSOleksandr Tymoshenko 	channel->need_reg_write = 0;
686e53470feSOleksandr Tymoshenko 
687e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
688e53470feSOleksandr Tymoshenko 
689e53470feSOleksandr Tymoshenko 	return (0);
690e53470feSOleksandr Tymoshenko }
691e53470feSOleksandr Tymoshenko 
692e53470feSOleksandr Tymoshenko /**
693e53470feSOleksandr Tymoshenko  *	ti_sdma_start_xfer_packet - starts a packet DMA transfer
694e53470feSOleksandr Tymoshenko  *	@ch: the channel number to use for the transfer
695e53470feSOleksandr Tymoshenko  *	@src_paddr: the source physical address
696e53470feSOleksandr Tymoshenko  *	@dst_paddr: the destination physical address
697e53470feSOleksandr Tymoshenko  *	@frmcnt: the number of frames to transfer
698e53470feSOleksandr Tymoshenko  *	@elmcnt: the number of elements in a frame, an element is either an 8, 16
699e53470feSOleksandr Tymoshenko  *           or 32-bit value as defined by ti_sdma_set_xfer_burst()
700e53470feSOleksandr Tymoshenko  *	@pktsize: the number of elements in each transfer packet
701e53470feSOleksandr Tymoshenko  *
702e53470feSOleksandr Tymoshenko  *	The @frmcnt and @elmcnt define the overall number of bytes to transfer,
703e53470feSOleksandr Tymoshenko  *	typically @frmcnt is 1 and @elmcnt contains the total number of elements.
704e53470feSOleksandr Tymoshenko  *	@pktsize is the size of each individual packet, there might be multiple
705e53470feSOleksandr Tymoshenko  *	packets per transfer.  i.e. for the following with element size of 32-bits
706e53470feSOleksandr Tymoshenko  *
707e53470feSOleksandr Tymoshenko  *		frmcnt = 1, elmcnt = 512, pktsize = 128
708e53470feSOleksandr Tymoshenko  *
709e53470feSOleksandr Tymoshenko  *	       Total transfer bytes = 1 * 512 = 512 elements or 2048 bytes
710*255eff3bSPedro F. Giffuni  *	       Packets transferred   = 128 / 512 = 4
711e53470feSOleksandr Tymoshenko  *
712e53470feSOleksandr Tymoshenko  *
713e53470feSOleksandr Tymoshenko  *	LOCKING:
714e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
715e53470feSOleksandr Tymoshenko  *
716e53470feSOleksandr Tymoshenko  *	RETURNS:
717e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
718e53470feSOleksandr Tymoshenko  */
719e53470feSOleksandr Tymoshenko int
720e53470feSOleksandr Tymoshenko ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr,
721e53470feSOleksandr Tymoshenko                            unsigned long dst_paddr, unsigned int frmcnt,
722e53470feSOleksandr Tymoshenko                            unsigned int elmcnt, unsigned int pktsize)
723e53470feSOleksandr Tymoshenko {
724e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
725e53470feSOleksandr Tymoshenko 	struct ti_sdma_channel *channel;
726e53470feSOleksandr Tymoshenko 	uint32_t ccr;
727e53470feSOleksandr Tymoshenko 
728e53470feSOleksandr Tymoshenko 	/* Sanity check */
729e53470feSOleksandr Tymoshenko 	if (sc == NULL)
730e53470feSOleksandr Tymoshenko 		return (ENOMEM);
731e53470feSOleksandr Tymoshenko 
732e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
733e53470feSOleksandr Tymoshenko 
734e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
735e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
736e53470feSOleksandr Tymoshenko 		return (EINVAL);
737e53470feSOleksandr Tymoshenko 	}
738e53470feSOleksandr Tymoshenko 
739e53470feSOleksandr Tymoshenko 	channel = &sc->sc_channel[ch];
740e53470feSOleksandr Tymoshenko 
741e53470feSOleksandr Tymoshenko 	/* a) Write the CSDP register */
742e53470feSOleksandr Tymoshenko 	if (channel->need_reg_write)
743e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_CSDP(ch),
744e53470feSOleksandr Tymoshenko 		    channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
745e53470feSOleksandr Tymoshenko 
746e53470feSOleksandr Tymoshenko 	/* b) Set the number of elements to transfer CEN[23:0] */
747e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
748e53470feSOleksandr Tymoshenko 
749e53470feSOleksandr Tymoshenko 	/* c) Set the number of frames to transfer CFN[15:0] */
750e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
751e53470feSOleksandr Tymoshenko 
752e53470feSOleksandr Tymoshenko 	/* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */
753e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
754e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
755e53470feSOleksandr Tymoshenko 
756e53470feSOleksandr Tymoshenko 	/* e) Write the CCR register */
757e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch),
758e53470feSOleksandr Tymoshenko 	    channel->reg_ccr | DMA4_CCR_PACKET_TRANS);
759e53470feSOleksandr Tymoshenko 
760e53470feSOleksandr Tymoshenko 	/* f)  - Set the source element index increment CSEI[15:0] */
761e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
762e53470feSOleksandr Tymoshenko 
763e53470feSOleksandr Tymoshenko 	/*     - Set the packet size, this is dependent on the sync source */
764e53470feSOleksandr Tymoshenko 	if (channel->reg_ccr & DMA4_CCR_SEL_SRC_DST_SYNC(1))
765e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_CSF(ch), pktsize);
766e53470feSOleksandr Tymoshenko 	else
767e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_CDF(ch), pktsize);
768e53470feSOleksandr Tymoshenko 
769e53470feSOleksandr Tymoshenko 	/* - Set the destination frame index increment CDFI[31:0] */
770e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
771e53470feSOleksandr Tymoshenko 
772e53470feSOleksandr Tymoshenko 	/* Clear the status register */
773e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
774e53470feSOleksandr Tymoshenko 
775e53470feSOleksandr Tymoshenko 	/* Write the start-bit and away we go */
776e53470feSOleksandr Tymoshenko 	ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
777e53470feSOleksandr Tymoshenko 	ccr |= (1 << 7);
778e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
779e53470feSOleksandr Tymoshenko 
780e53470feSOleksandr Tymoshenko 	/* Clear the reg write flag */
781e53470feSOleksandr Tymoshenko 	channel->need_reg_write = 0;
782e53470feSOleksandr Tymoshenko 
783e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
784e53470feSOleksandr Tymoshenko 
785e53470feSOleksandr Tymoshenko 	return (0);
786e53470feSOleksandr Tymoshenko }
787e53470feSOleksandr Tymoshenko 
788e53470feSOleksandr Tymoshenko /**
789e53470feSOleksandr Tymoshenko  *	ti_sdma_stop_xfer - stops any currently active transfers
790*255eff3bSPedro F. Giffuni  *	@ch: the channel number to set the endianness of
791e53470feSOleksandr Tymoshenko  *
792e53470feSOleksandr Tymoshenko  *	This function call is effectively a NOP if no transaction is in progress.
793e53470feSOleksandr Tymoshenko  *
794e53470feSOleksandr Tymoshenko  *	LOCKING:
795e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
796e53470feSOleksandr Tymoshenko  *
797e53470feSOleksandr Tymoshenko  *	RETURNS:
798e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
799e53470feSOleksandr Tymoshenko  */
800e53470feSOleksandr Tymoshenko int
801e53470feSOleksandr Tymoshenko ti_sdma_stop_xfer(unsigned int ch)
802e53470feSOleksandr Tymoshenko {
803e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
804e53470feSOleksandr Tymoshenko 	unsigned int j;
805e53470feSOleksandr Tymoshenko 
806e53470feSOleksandr Tymoshenko 	/* Sanity check */
807e53470feSOleksandr Tymoshenko 	if (sc == NULL)
808e53470feSOleksandr Tymoshenko 		return (ENOMEM);
809e53470feSOleksandr Tymoshenko 
810e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
811e53470feSOleksandr Tymoshenko 
812e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
813e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
814e53470feSOleksandr Tymoshenko 		return (EINVAL);
815e53470feSOleksandr Tymoshenko 	}
816e53470feSOleksandr Tymoshenko 
817e53470feSOleksandr Tymoshenko 	/* Disable all DMA interrupts for the channel. */
818e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
819e53470feSOleksandr Tymoshenko 
820e53470feSOleksandr Tymoshenko 	/* Make sure the DMA transfer is stopped. */
821e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
822e53470feSOleksandr Tymoshenko 
823e53470feSOleksandr Tymoshenko 	/* Clear the CSR register and IRQ status register */
824e53470feSOleksandr Tymoshenko 	ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
825e53470feSOleksandr Tymoshenko 	for (j = 0; j < NUM_DMA_IRQS; j++) {
826e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
827e53470feSOleksandr Tymoshenko 	}
828e53470feSOleksandr Tymoshenko 
829e53470feSOleksandr Tymoshenko 	/* Configuration registers need to be re-written on the next xfer */
830e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
831e53470feSOleksandr Tymoshenko 
832e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
833e53470feSOleksandr Tymoshenko 
834e53470feSOleksandr Tymoshenko 	return (0);
835e53470feSOleksandr Tymoshenko }
836e53470feSOleksandr Tymoshenko 
837e53470feSOleksandr Tymoshenko /**
838*255eff3bSPedro F. Giffuni  *	ti_sdma_set_xfer_endianess - sets the endianness of subsequent transfers
839*255eff3bSPedro F. Giffuni  *	@ch: the channel number to set the endianness of
840*255eff3bSPedro F. Giffuni  *	@src: the source endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG)
841*255eff3bSPedro F. Giffuni  *	@dst: the destination endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG)
842e53470feSOleksandr Tymoshenko  *
843e53470feSOleksandr Tymoshenko  *
844e53470feSOleksandr Tymoshenko  *	LOCKING:
845e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
846e53470feSOleksandr Tymoshenko  *
847e53470feSOleksandr Tymoshenko  *	RETURNS:
848e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
849e53470feSOleksandr Tymoshenko  */
850e53470feSOleksandr Tymoshenko int
851e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst)
852e53470feSOleksandr Tymoshenko {
853e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
854e53470feSOleksandr Tymoshenko 
855e53470feSOleksandr Tymoshenko 	/* Sanity check */
856e53470feSOleksandr Tymoshenko 	if (sc == NULL)
857e53470feSOleksandr Tymoshenko 		return (ENOMEM);
858e53470feSOleksandr Tymoshenko 
859e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
860e53470feSOleksandr Tymoshenko 
861e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
862e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
863e53470feSOleksandr Tymoshenko 		return (EINVAL);
864e53470feSOleksandr Tymoshenko 	}
865e53470feSOleksandr Tymoshenko 
866e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_ENDIANISM(1);
867e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_ENDIANISM(src);
868e53470feSOleksandr Tymoshenko 
869e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_ENDIANISM(1);
870e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_ENDIANISM(dst);
871e53470feSOleksandr Tymoshenko 
872e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
873e53470feSOleksandr Tymoshenko 
874e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
875e53470feSOleksandr Tymoshenko 
876e53470feSOleksandr Tymoshenko 	return 0;
877e53470feSOleksandr Tymoshenko }
878e53470feSOleksandr Tymoshenko 
879e53470feSOleksandr Tymoshenko /**
880e53470feSOleksandr Tymoshenko  *	ti_sdma_set_xfer_burst - sets the source and destination element size
881e53470feSOleksandr Tymoshenko  *	@ch: the channel number to set the burst settings of
882*255eff3bSPedro F. Giffuni  *	@src: the source endianness (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32
883e53470feSOleksandr Tymoshenko  *	      or DMA_BURST_64)
884*255eff3bSPedro F. Giffuni  *	@dst: the destination endianness (either DMA_BURST_NONE, DMA_BURST_16,
885e53470feSOleksandr Tymoshenko  *	      DMA_BURST_32 or DMA_BURST_64)
886e53470feSOleksandr Tymoshenko  *
887e53470feSOleksandr Tymoshenko  *	This function sets the size of the elements for all subsequent transfers.
888e53470feSOleksandr Tymoshenko  *
889e53470feSOleksandr Tymoshenko  *	LOCKING:
890e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
891e53470feSOleksandr Tymoshenko  *
892e53470feSOleksandr Tymoshenko  *	RETURNS:
893e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
894e53470feSOleksandr Tymoshenko  */
895e53470feSOleksandr Tymoshenko int
896e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst)
897e53470feSOleksandr Tymoshenko {
898e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
899e53470feSOleksandr Tymoshenko 
900e53470feSOleksandr Tymoshenko 	/* Sanity check */
901e53470feSOleksandr Tymoshenko 	if (sc == NULL)
902e53470feSOleksandr Tymoshenko 		return (ENOMEM);
903e53470feSOleksandr Tymoshenko 
904e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
905e53470feSOleksandr Tymoshenko 
906e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
907e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
908e53470feSOleksandr Tymoshenko 		return (EINVAL);
909e53470feSOleksandr Tymoshenko 	}
910e53470feSOleksandr Tymoshenko 
911e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_BURST_MODE(0x3);
912e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_BURST_MODE(src);
913e53470feSOleksandr Tymoshenko 
914e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_BURST_MODE(0x3);
915e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_BURST_MODE(dst);
916e53470feSOleksandr Tymoshenko 
917e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
918e53470feSOleksandr Tymoshenko 
919e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
920e53470feSOleksandr Tymoshenko 
921e53470feSOleksandr Tymoshenko 	return 0;
922e53470feSOleksandr Tymoshenko }
923e53470feSOleksandr Tymoshenko 
924e53470feSOleksandr Tymoshenko /**
925e53470feSOleksandr Tymoshenko  *	ti_sdma_set_xfer_data_type - driver attach function
926*255eff3bSPedro F. Giffuni  *	@ch: the channel number to set the endianness of
927e53470feSOleksandr Tymoshenko  *	@type: the xfer data type (either DMA_DATA_8BITS_SCALAR, DMA_DATA_16BITS_SCALAR
928e53470feSOleksandr Tymoshenko  *	       or DMA_DATA_32BITS_SCALAR)
929e53470feSOleksandr Tymoshenko  *
930e53470feSOleksandr Tymoshenko  *
931e53470feSOleksandr Tymoshenko  *	LOCKING:
932e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
933e53470feSOleksandr Tymoshenko  *
934e53470feSOleksandr Tymoshenko  *	RETURNS:
935e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
936e53470feSOleksandr Tymoshenko  */
937e53470feSOleksandr Tymoshenko int
938e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type)
939e53470feSOleksandr Tymoshenko {
940e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
941e53470feSOleksandr Tymoshenko 
942e53470feSOleksandr Tymoshenko 	/* Sanity check */
943e53470feSOleksandr Tymoshenko 	if (sc == NULL)
944e53470feSOleksandr Tymoshenko 		return (ENOMEM);
945e53470feSOleksandr Tymoshenko 
946e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
947e53470feSOleksandr Tymoshenko 
948e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
949e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
950e53470feSOleksandr Tymoshenko 		return (EINVAL);
951e53470feSOleksandr Tymoshenko 	}
952e53470feSOleksandr Tymoshenko 
953e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DATA_TYPE(0x3);
954e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DATA_TYPE(type);
955e53470feSOleksandr Tymoshenko 
956e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
957e53470feSOleksandr Tymoshenko 
958e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
959e53470feSOleksandr Tymoshenko 
960e53470feSOleksandr Tymoshenko 	return 0;
961e53470feSOleksandr Tymoshenko }
962e53470feSOleksandr Tymoshenko 
963e53470feSOleksandr Tymoshenko /**
964e53470feSOleksandr Tymoshenko  *	ti_sdma_set_callback - driver attach function
965e53470feSOleksandr Tymoshenko  *	@dev: dma device handle
966e53470feSOleksandr Tymoshenko  *
967e53470feSOleksandr Tymoshenko  *
968e53470feSOleksandr Tymoshenko  *
969e53470feSOleksandr Tymoshenko  *	LOCKING:
970e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
971e53470feSOleksandr Tymoshenko  *
972e53470feSOleksandr Tymoshenko  *	RETURNS:
973e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
974e53470feSOleksandr Tymoshenko  */
975e53470feSOleksandr Tymoshenko int
976e53470feSOleksandr Tymoshenko ti_sdma_set_callback(unsigned int ch,
977e53470feSOleksandr Tymoshenko                       void (*callback)(unsigned int ch, uint32_t status, void *data),
978e53470feSOleksandr Tymoshenko                       void *data)
979e53470feSOleksandr Tymoshenko {
980e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
981e53470feSOleksandr Tymoshenko 
982e53470feSOleksandr Tymoshenko 	/* Sanity check */
983e53470feSOleksandr Tymoshenko 	if (sc == NULL)
984e53470feSOleksandr Tymoshenko 		return (ENOMEM);
985e53470feSOleksandr Tymoshenko 
986e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
987e53470feSOleksandr Tymoshenko 
988e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
989e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
990e53470feSOleksandr Tymoshenko 		return (EINVAL);
991e53470feSOleksandr Tymoshenko 	}
992e53470feSOleksandr Tymoshenko 
993e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].callback = callback;
994e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].callback_data = data;
995e53470feSOleksandr Tymoshenko 
996e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
997e53470feSOleksandr Tymoshenko 
998e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
999e53470feSOleksandr Tymoshenko 
1000e53470feSOleksandr Tymoshenko 	return 0;
1001e53470feSOleksandr Tymoshenko }
1002e53470feSOleksandr Tymoshenko 
1003e53470feSOleksandr Tymoshenko /**
1004e53470feSOleksandr Tymoshenko  *	ti_sdma_sync_params - sets channel sync settings
1005e53470feSOleksandr Tymoshenko  *	@ch: the channel number to set the sync on
1006e53470feSOleksandr Tymoshenko  *	@trigger: the number of the sync trigger, this depends on what other H/W
1007e53470feSOleksandr Tymoshenko  *	          module is triggering/receiving the DMA transactions
1008e53470feSOleksandr Tymoshenko  *	@mode: flags describing the sync mode to use, it may have one or more of
1009e53470feSOleksandr Tymoshenko  *	          the following bits set; TI_SDMA_SYNC_FRAME,
1010e53470feSOleksandr Tymoshenko  *	          TI_SDMA_SYNC_BLOCK, TI_SDMA_SYNC_TRIG_ON_SRC.
1011e53470feSOleksandr Tymoshenko  *
1012e53470feSOleksandr Tymoshenko  *
1013e53470feSOleksandr Tymoshenko  *
1014e53470feSOleksandr Tymoshenko  *	LOCKING:
1015e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
1016e53470feSOleksandr Tymoshenko  *
1017e53470feSOleksandr Tymoshenko  *	RETURNS:
1018e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
1019e53470feSOleksandr Tymoshenko  */
1020e53470feSOleksandr Tymoshenko int
1021e53470feSOleksandr Tymoshenko ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode)
1022e53470feSOleksandr Tymoshenko {
1023e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
1024e53470feSOleksandr Tymoshenko 	uint32_t ccr;
1025e53470feSOleksandr Tymoshenko 
1026e53470feSOleksandr Tymoshenko 	/* Sanity check */
1027e53470feSOleksandr Tymoshenko 	if (sc == NULL)
1028e53470feSOleksandr Tymoshenko 		return (ENOMEM);
1029e53470feSOleksandr Tymoshenko 
1030e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
1031e53470feSOleksandr Tymoshenko 
1032e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
1033e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
1034e53470feSOleksandr Tymoshenko 		return (EINVAL);
1035e53470feSOleksandr Tymoshenko 	}
1036e53470feSOleksandr Tymoshenko 
1037e53470feSOleksandr Tymoshenko 	ccr = sc->sc_channel[ch].reg_ccr;
1038e53470feSOleksandr Tymoshenko 
1039e53470feSOleksandr Tymoshenko 	ccr &= ~DMA4_CCR_SYNC_TRIGGER(0x7F);
1040e53470feSOleksandr Tymoshenko 	ccr |= DMA4_CCR_SYNC_TRIGGER(trigger + 1);
1041e53470feSOleksandr Tymoshenko 
1042e53470feSOleksandr Tymoshenko 	if (mode & TI_SDMA_SYNC_FRAME)
1043e53470feSOleksandr Tymoshenko 		ccr |= DMA4_CCR_FRAME_SYNC(1);
1044e53470feSOleksandr Tymoshenko 	else
1045e53470feSOleksandr Tymoshenko 		ccr &= ~DMA4_CCR_FRAME_SYNC(1);
1046e53470feSOleksandr Tymoshenko 
1047e53470feSOleksandr Tymoshenko 	if (mode & TI_SDMA_SYNC_BLOCK)
1048e53470feSOleksandr Tymoshenko 		ccr |= DMA4_CCR_BLOCK_SYNC(1);
1049e53470feSOleksandr Tymoshenko 	else
1050e53470feSOleksandr Tymoshenko 		ccr &= ~DMA4_CCR_BLOCK_SYNC(1);
1051e53470feSOleksandr Tymoshenko 
1052e53470feSOleksandr Tymoshenko 	if (mode & TI_SDMA_SYNC_TRIG_ON_SRC)
1053e53470feSOleksandr Tymoshenko 		ccr |= DMA4_CCR_SEL_SRC_DST_SYNC(1);
1054e53470feSOleksandr Tymoshenko 	else
1055e53470feSOleksandr Tymoshenko 		ccr &= ~DMA4_CCR_SEL_SRC_DST_SYNC(1);
1056e53470feSOleksandr Tymoshenko 
1057e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_ccr = ccr;
1058e53470feSOleksandr Tymoshenko 
1059e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
1060e53470feSOleksandr Tymoshenko 
1061e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
1062e53470feSOleksandr Tymoshenko 
1063e53470feSOleksandr Tymoshenko 	return 0;
1064e53470feSOleksandr Tymoshenko }
1065e53470feSOleksandr Tymoshenko 
1066e53470feSOleksandr Tymoshenko /**
1067e53470feSOleksandr Tymoshenko  *	ti_sdma_set_addr_mode - driver attach function
1068*255eff3bSPedro F. Giffuni  *	@ch: the channel number to set the endianness of
1069e53470feSOleksandr Tymoshenko  *	@rd_mode: the xfer source addressing mode (either DMA_ADDR_CONSTANT,
1070e53470feSOleksandr Tymoshenko  *	          DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or
1071e53470feSOleksandr Tymoshenko  *	          DMA_ADDR_DOUBLE_INDEX)
1072e53470feSOleksandr Tymoshenko  *	@wr_mode: the xfer destination addressing mode (either DMA_ADDR_CONSTANT,
1073e53470feSOleksandr Tymoshenko  *	          DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or
1074e53470feSOleksandr Tymoshenko  *	          DMA_ADDR_DOUBLE_INDEX)
1075e53470feSOleksandr Tymoshenko  *
1076e53470feSOleksandr Tymoshenko  *
1077e53470feSOleksandr Tymoshenko  *	LOCKING:
1078e53470feSOleksandr Tymoshenko  *	DMA registers protected by internal mutex
1079e53470feSOleksandr Tymoshenko  *
1080e53470feSOleksandr Tymoshenko  *	RETURNS:
1081e53470feSOleksandr Tymoshenko  *	EH_HANDLED or EH_NOT_HANDLED
1082e53470feSOleksandr Tymoshenko  */
1083e53470feSOleksandr Tymoshenko int
1084e53470feSOleksandr Tymoshenko ti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode,
1085e53470feSOleksandr Tymoshenko                        unsigned int dst_mode)
1086e53470feSOleksandr Tymoshenko {
1087e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = ti_sdma_sc;
1088e53470feSOleksandr Tymoshenko 	uint32_t ccr;
1089e53470feSOleksandr Tymoshenko 
1090e53470feSOleksandr Tymoshenko 	/* Sanity check */
1091e53470feSOleksandr Tymoshenko 	if (sc == NULL)
1092e53470feSOleksandr Tymoshenko 		return (ENOMEM);
1093e53470feSOleksandr Tymoshenko 
1094e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK(sc);
1095e53470feSOleksandr Tymoshenko 
1096e53470feSOleksandr Tymoshenko 	if ((sc->sc_active_channels & (1 << ch)) == 0) {
1097e53470feSOleksandr Tymoshenko 		TI_SDMA_UNLOCK(sc);
1098e53470feSOleksandr Tymoshenko 		return (EINVAL);
1099e53470feSOleksandr Tymoshenko 	}
1100e53470feSOleksandr Tymoshenko 
1101e53470feSOleksandr Tymoshenko 	ccr = sc->sc_channel[ch].reg_ccr;
1102e53470feSOleksandr Tymoshenko 
1103e53470feSOleksandr Tymoshenko 	ccr &= ~DMA4_CCR_SRC_ADDRESS_MODE(0x3);
1104e53470feSOleksandr Tymoshenko 	ccr |= DMA4_CCR_SRC_ADDRESS_MODE(src_mode);
1105e53470feSOleksandr Tymoshenko 
1106e53470feSOleksandr Tymoshenko 	ccr &= ~DMA4_CCR_DST_ADDRESS_MODE(0x3);
1107e53470feSOleksandr Tymoshenko 	ccr |= DMA4_CCR_DST_ADDRESS_MODE(dst_mode);
1108e53470feSOleksandr Tymoshenko 
1109e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].reg_ccr = ccr;
1110e53470feSOleksandr Tymoshenko 
1111e53470feSOleksandr Tymoshenko 	sc->sc_channel[ch].need_reg_write = 1;
1112e53470feSOleksandr Tymoshenko 
1113e53470feSOleksandr Tymoshenko 	TI_SDMA_UNLOCK(sc);
1114e53470feSOleksandr Tymoshenko 
1115e53470feSOleksandr Tymoshenko 	return 0;
1116e53470feSOleksandr Tymoshenko }
1117e53470feSOleksandr Tymoshenko 
1118e53470feSOleksandr Tymoshenko /**
1119e53470feSOleksandr Tymoshenko  *	ti_sdma_probe - driver probe function
1120e53470feSOleksandr Tymoshenko  *	@dev: dma device handle
1121e53470feSOleksandr Tymoshenko  *
1122e53470feSOleksandr Tymoshenko  *
1123e53470feSOleksandr Tymoshenko  *
1124e53470feSOleksandr Tymoshenko  *	RETURNS:
1125e53470feSOleksandr Tymoshenko  *	Always returns 0.
1126e53470feSOleksandr Tymoshenko  */
1127e53470feSOleksandr Tymoshenko static int
1128e53470feSOleksandr Tymoshenko ti_sdma_probe(device_t dev)
1129e53470feSOleksandr Tymoshenko {
1130add35ed5SIan Lepore 
1131add35ed5SIan Lepore 	if (!ofw_bus_status_okay(dev))
1132add35ed5SIan Lepore 		return (ENXIO);
1133add35ed5SIan Lepore 
11345b03aba6SOleksandr Tymoshenko 	if (!ofw_bus_is_compatible(dev, "ti,omap4430-sdma"))
1135e53470feSOleksandr Tymoshenko 		return (ENXIO);
1136e53470feSOleksandr Tymoshenko 
1137e53470feSOleksandr Tymoshenko 	device_set_desc(dev, "TI sDMA Controller");
1138e53470feSOleksandr Tymoshenko 	return (0);
1139e53470feSOleksandr Tymoshenko }
1140e53470feSOleksandr Tymoshenko 
1141e53470feSOleksandr Tymoshenko /**
1142e53470feSOleksandr Tymoshenko  *	ti_sdma_attach - driver attach function
1143e53470feSOleksandr Tymoshenko  *	@dev: dma device handle
1144e53470feSOleksandr Tymoshenko  *
1145e53470feSOleksandr Tymoshenko  *	Initialises memory mapping/pointers to the DMA register set and requests
1146e53470feSOleksandr Tymoshenko  *	IRQs. This is effectively the setup function for the driver.
1147e53470feSOleksandr Tymoshenko  *
1148e53470feSOleksandr Tymoshenko  *	RETURNS:
1149e53470feSOleksandr Tymoshenko  *	0 on success or a negative error code failure.
1150e53470feSOleksandr Tymoshenko  */
1151e53470feSOleksandr Tymoshenko static int
1152e53470feSOleksandr Tymoshenko ti_sdma_attach(device_t dev)
1153e53470feSOleksandr Tymoshenko {
1154e53470feSOleksandr Tymoshenko 	struct ti_sdma_softc *sc = device_get_softc(dev);
1155e53470feSOleksandr Tymoshenko 	unsigned int timeout;
1156e53470feSOleksandr Tymoshenko 	unsigned int i;
1157e53470feSOleksandr Tymoshenko 	int      rid;
1158e53470feSOleksandr Tymoshenko 	void    *ihl;
1159e53470feSOleksandr Tymoshenko 	int      err;
1160e53470feSOleksandr Tymoshenko 
1161e53470feSOleksandr Tymoshenko 	/* Setup the basics */
1162e53470feSOleksandr Tymoshenko 	sc->sc_dev = dev;
1163e53470feSOleksandr Tymoshenko 
1164e53470feSOleksandr Tymoshenko 	/* No channels active at the moment */
1165e53470feSOleksandr Tymoshenko 	sc->sc_active_channels = 0x00000000;
1166e53470feSOleksandr Tymoshenko 
1167e53470feSOleksandr Tymoshenko 	/* Mutex to protect the shared data structures */
1168e53470feSOleksandr Tymoshenko 	TI_SDMA_LOCK_INIT(sc);
1169e53470feSOleksandr Tymoshenko 
1170e53470feSOleksandr Tymoshenko 	/* Get the memory resource for the register mapping */
1171e53470feSOleksandr Tymoshenko 	rid = 0;
1172e53470feSOleksandr Tymoshenko 	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
1173e53470feSOleksandr Tymoshenko 	if (sc->sc_mem_res == NULL)
1174e53470feSOleksandr Tymoshenko 		panic("%s: Cannot map registers", device_get_name(dev));
1175e53470feSOleksandr Tymoshenko 
1176e53470feSOleksandr Tymoshenko 	/* Enable the interface and functional clocks */
1177e53470feSOleksandr Tymoshenko 	ti_prcm_clk_enable(SDMA_CLK);
1178e53470feSOleksandr Tymoshenko 
1179e53470feSOleksandr Tymoshenko 	/* Read the sDMA revision register and sanity check it's known */
1180e53470feSOleksandr Tymoshenko 	sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION);
1181e53470feSOleksandr Tymoshenko 	device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev);
1182e53470feSOleksandr Tymoshenko 
1183e53470feSOleksandr Tymoshenko 	if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) {
1184e53470feSOleksandr Tymoshenko 		device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n");
1185e53470feSOleksandr Tymoshenko 		return (EINVAL);
1186e53470feSOleksandr Tymoshenko 	}
1187e53470feSOleksandr Tymoshenko 
1188e53470feSOleksandr Tymoshenko 	/* Disable all interrupts */
1189e53470feSOleksandr Tymoshenko 	for (i = 0; i < NUM_DMA_IRQS; i++) {
1190e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000);
1191e53470feSOleksandr Tymoshenko 	}
1192e53470feSOleksandr Tymoshenko 
1193e53470feSOleksandr Tymoshenko 	/* Soft-reset is only supported on pre-OMAP44xx devices */
1194e53470feSOleksandr Tymoshenko 	if (ti_sdma_is_omap3_rev(sc)) {
1195e53470feSOleksandr Tymoshenko 
1196e53470feSOleksandr Tymoshenko 		/* Soft-reset */
1197e53470feSOleksandr Tymoshenko 		ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002);
1198e53470feSOleksandr Tymoshenko 
1199e53470feSOleksandr Tymoshenko 		/* Set the timeout to 100ms*/
1200e53470feSOleksandr Tymoshenko 		timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
1201e53470feSOleksandr Tymoshenko 
1202e53470feSOleksandr Tymoshenko 		/* Wait for DMA reset to complete */
1203e53470feSOleksandr Tymoshenko 		while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) {
1204e53470feSOleksandr Tymoshenko 
1205e53470feSOleksandr Tymoshenko 			/* Sleep for a tick */
1206e53470feSOleksandr Tymoshenko 			pause("DMARESET", 1);
1207e53470feSOleksandr Tymoshenko 
1208e53470feSOleksandr Tymoshenko 			if (timeout-- == 0) {
1209e53470feSOleksandr Tymoshenko 				device_printf(sc->sc_dev, "sDMA reset operation timed out\n");
1210e53470feSOleksandr Tymoshenko 				return (EINVAL);
1211e53470feSOleksandr Tymoshenko 			}
1212e53470feSOleksandr Tymoshenko 		}
1213e53470feSOleksandr Tymoshenko 	}
1214e53470feSOleksandr Tymoshenko 
1215e53470feSOleksandr Tymoshenko 	/*
1216e53470feSOleksandr Tymoshenko 	 * Install interrupt handlers for the for possible interrupts. Any channel
1217e53470feSOleksandr Tymoshenko 	 * can trip one of the four IRQs
1218e53470feSOleksandr Tymoshenko 	 */
1219e53470feSOleksandr Tymoshenko 	rid = 0;
1220e53470feSOleksandr Tymoshenko 	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
1221e53470feSOleksandr Tymoshenko 	    RF_ACTIVE | RF_SHAREABLE);
1222e53470feSOleksandr Tymoshenko 	if (sc->sc_irq_res == NULL)
1223e53470feSOleksandr Tymoshenko 		panic("Unable to setup the dma irq handler.\n");
1224e53470feSOleksandr Tymoshenko 
1225e53470feSOleksandr Tymoshenko 	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
1226e53470feSOleksandr Tymoshenko 	    NULL, ti_sdma_intr, NULL, &ihl);
1227e53470feSOleksandr Tymoshenko 	if (err)
1228e53470feSOleksandr Tymoshenko 		panic("%s: Cannot register IRQ", device_get_name(dev));
1229e53470feSOleksandr Tymoshenko 
1230e53470feSOleksandr Tymoshenko 	/* Store the DMA structure globally ... this driver should never be unloaded */
1231e53470feSOleksandr Tymoshenko 	ti_sdma_sc = sc;
1232e53470feSOleksandr Tymoshenko 
1233e53470feSOleksandr Tymoshenko 	return (0);
1234e53470feSOleksandr Tymoshenko }
1235e53470feSOleksandr Tymoshenko 
1236e53470feSOleksandr Tymoshenko static device_method_t ti_sdma_methods[] = {
1237e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_probe, ti_sdma_probe),
1238e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_attach, ti_sdma_attach),
1239e53470feSOleksandr Tymoshenko 	{0, 0},
1240e53470feSOleksandr Tymoshenko };
1241e53470feSOleksandr Tymoshenko 
1242e53470feSOleksandr Tymoshenko static driver_t ti_sdma_driver = {
1243e53470feSOleksandr Tymoshenko 	"ti_sdma",
1244e53470feSOleksandr Tymoshenko 	ti_sdma_methods,
1245e53470feSOleksandr Tymoshenko 	sizeof(struct ti_sdma_softc),
1246e53470feSOleksandr Tymoshenko };
1247e53470feSOleksandr Tymoshenko static devclass_t ti_sdma_devclass;
1248e53470feSOleksandr Tymoshenko 
1249e53470feSOleksandr Tymoshenko DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0);
1250e53470feSOleksandr Tymoshenko MODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1);
1251