1/*-
2 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
3 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of authors nor the names of its contributors may be
15 *    used to endorse or promote products derived from this software without
16 *    specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/endian.h>
37#include <sys/mbuf.h>
38#include <sys/lock.h>
39#include <sys/mutex.h>
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/socket.h>
43#include <sys/sysctl.h>
44
45#include <sys/sockio.h>
46#include <sys/bus.h>
47#include <machine/bus.h>
48#include <sys/rman.h>
49#include <machine/resource.h>
50
51#include <dev/fdt/fdt_common.h>
52#include <dev/ofw/ofw_bus.h>
53#include <dev/ofw/ofw_bus_subr.h>
54
55#include <arm/ti/ti_scm.h>
56#include <arm/ti/ti_prcm.h>
57
58#include <arm/ti/ti_edma3.h>
59
60#define TI_EDMA3_NUM_TCS		3
61#define TI_EDMA3_NUM_IRQS		3
62#define TI_EDMA3_NUM_DMA_CHS		64
63#define TI_EDMA3_NUM_QDMA_CHS		8
64
65#define TI_EDMA3CC_PID			0x000
66#define TI_EDMA3CC_DCHMAP(p)		(0x100 + ((p)*4))
67#define TI_EDMA3CC_DMAQNUM(n)		(0x240 + ((n)*4))
68#define TI_EDMA3CC_QDMAQNUM		0x260
69#define TI_EDMA3CC_EMCR			0x308
70#define TI_EDMA3CC_EMCRH		0x30C
71#define TI_EDMA3CC_QEMCR		0x314
72#define TI_EDMA3CC_CCERR		0x318
73#define TI_EDMA3CC_CCERRCLR		0x31C
74#define TI_EDMA3CC_DRAE(p)		(0x340 + ((p)*8))
75#define TI_EDMA3CC_DRAEH(p)		(0x344 + ((p)*8))
76#define TI_EDMA3CC_QRAE(p)		(0x380 + ((p)*4))
77#define TI_EDMA3CC_S_ESR(p)		(0x2010 + ((p)*0x200))
78#define TI_EDMA3CC_S_ESRH(p)		(0x2014 + ((p)*0x200))
79#define TI_EDMA3CC_S_SECR(p)		(0x2040 + ((p)*0x200))
80#define TI_EDMA3CC_S_SECRH(p)		(0x2044 + ((p)*0x200))
81#define TI_EDMA3CC_S_EESR(p)		(0x2030 + ((p)*0x200))
82#define TI_EDMA3CC_S_EESRH(p)		(0x2034 + ((p)*0x200))
83#define TI_EDMA3CC_S_IESR(p)		(0x2060 + ((p)*0x200))
84#define TI_EDMA3CC_S_IESRH(p)		(0x2064 + ((p)*0x200))
85#define TI_EDMA3CC_S_IPR(p)		(0x2068 + ((p)*0x200))
86#define TI_EDMA3CC_S_IPRH(p)		(0x206C + ((p)*0x200))
87#define TI_EDMA3CC_S_QEESR(p)		(0x208C + ((p)*0x200))
88
89#define TI_EDMA3CC_PARAM_OFFSET		0x4000
90#define TI_EDMA3CC_OPT(p)		(TI_EDMA3CC_PARAM_OFFSET + 0x0 + ((p)*0x20))
91
92#define TI_EDMA3CC_DMAQNUM_SET(c,q)	((0x7 & (q)) << (((c) % 8) * 4))
93#define TI_EDMA3CC_DMAQNUM_CLR(c)	(~(0x7 << (((c) % 8) * 4)))
94#define TI_EDMA3CC_QDMAQNUM_SET(c,q)	((0x7 & (q)) << ((c) * 4))
95#define TI_EDMA3CC_QDMAQNUM_CLR(c)	(~(0x7 << ((c) * 4)))
96
97#define TI_EDMA3CC_OPT_TCC_CLR		(~(0x3F000))
98#define TI_EDMA3CC_OPT_TCC_SET(p)	(((0x3F000 >> 12) & (p)) << 12)
99
100struct ti_edma3_softc {
101	device_t		sc_dev;
102	struct resource *	mem_res[TI_EDMA3_NUM_TCS+1];
103	struct resource *	irq_res[TI_EDMA3_NUM_IRQS];
104	void			*ih_cookie[TI_EDMA3_NUM_IRQS];
105};
106
107static struct ti_edma3_softc *ti_edma3_sc = NULL;
108
109static struct resource_spec ti_edma3_mem_spec[] = {
110	{ SYS_RES_MEMORY,   0,  RF_ACTIVE },
111	{ SYS_RES_MEMORY,   1,  RF_ACTIVE },
112	{ SYS_RES_MEMORY,   2,  RF_ACTIVE },
113	{ SYS_RES_MEMORY,   3,  RF_ACTIVE },
114	{ -1,               0,  0 }
115};
116static struct resource_spec ti_edma3_irq_spec[] = {
117	{ SYS_RES_IRQ,      0,  RF_ACTIVE },
118	{ SYS_RES_IRQ,      1,  RF_ACTIVE },
119	{ SYS_RES_IRQ,      2,  RF_ACTIVE },
120	{ -1,               0,  0 }
121};
122
123/* Read/Write macros */
124#define ti_edma3_cc_rd_4(reg)		bus_read_4(ti_edma3_sc->mem_res[0], reg)
125#define ti_edma3_cc_wr_4(reg, val)	bus_write_4(ti_edma3_sc->mem_res[0], reg, val)
126#define ti_edma3_tc_rd_4(c, reg)	bus_read_4(ti_edma3_sc->mem_res[c+1], reg)
127#define ti_edma3_tc_wr_4(c, reg, val)	bus_write_4(ti_edma3_sc->mem_res[c+1], reg, val)
128
129static void ti_edma3_intr_comp(void *arg);
130static void ti_edma3_intr_mperr(void *arg);
131static void ti_edma3_intr_err(void *arg);
132
133static struct {
134	driver_intr_t *handler;
135	char * description;
136} ti_edma3_intrs[TI_EDMA3_NUM_IRQS] = {
137	{ ti_edma3_intr_comp,	"EDMA Completion Interrupt" },
138	{ ti_edma3_intr_mperr,	"EDMA Memory Protection Error Interrupt" },
139	{ ti_edma3_intr_err,	"EDMA Error Interrupt" },
140};
141
142static int
143ti_edma3_probe(device_t dev)
144{
145	if (!ofw_bus_is_compatible(dev, "ti,edma3"))
146		return (ENXIO);
147
148	device_set_desc(dev, "TI EDMA Controller");
149	return (0);
150}
151
152static int
153ti_edma3_attach(device_t dev)
154{
155	struct ti_edma3_softc *sc = device_get_softc(dev);
156	uint32_t reg;
157	int err;
158	int i;
159
160	if (ti_edma3_sc)
161		return (ENXIO);
162
163	ti_edma3_sc = sc;
164	sc->sc_dev = dev;
165
166	/* Request the memory resources */
167	err = bus_alloc_resources(dev, ti_edma3_mem_spec, sc->mem_res);
168	if (err) {
169		device_printf(dev, "Error: could not allocate mem resources\n");
170		return (ENXIO);
171	}
172
173	/* Request the IRQ resources */
174	err = bus_alloc_resources(dev, ti_edma3_irq_spec, sc->irq_res);
175	if (err) {
176		device_printf(dev, "Error: could not allocate irq resources\n");
177		return (ENXIO);
178	}
179
180	/* Enable Channel Controller */
181	ti_prcm_clk_enable(EDMA_TPCC_CLK);
182
183	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID);
184
185	device_printf(dev, "EDMA revision %08x\n", reg);
186
187
188	/* Attach interrupt handlers */
189	for (i = 0; i < TI_EDMA3_NUM_IRQS; ++i) {
190		err = bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC |
191		    INTR_MPSAFE, NULL, *ti_edma3_intrs[i].handler,
192		    sc, &sc->ih_cookie[i]);
193		if (err) {
194			device_printf(dev, "could not setup %s\n",
195			    ti_edma3_intrs[i].description);
196			return (err);
197		}
198	}
199
200	return (0);
201}
202
203static device_method_t ti_edma3_methods[] = {
204	DEVMETHOD(device_probe, ti_edma3_probe),
205	DEVMETHOD(device_attach, ti_edma3_attach),
206	{0, 0},
207};
208
209static driver_t ti_edma3_driver = {
210	"ti_edma3",
211	ti_edma3_methods,
212	sizeof(struct ti_edma3_softc),
213};
214static devclass_t ti_edma3_devclass;
215
216DRIVER_MODULE(ti_edma3, simplebus, ti_edma3_driver, ti_edma3_devclass, 0, 0);
217MODULE_DEPEND(ti_edma3, ti_prcm, 1, 1, 1);
218
219static void
220ti_edma3_intr_comp(void *arg)
221{
222	printf("%s: unimplemented\n", __func__);
223}
224
225static void
226ti_edma3_intr_mperr(void *arg)
227{
228	printf("%s: unimplemented\n", __func__);
229}
230
231static void
232ti_edma3_intr_err(void *arg)
233{
234	printf("%s: unimplemented\n", __func__);
235}
236
237void
238ti_edma3_init(unsigned int eqn)
239{
240	uint32_t reg;
241	int i;
242
243	/* on AM335x Event queue 0 is always mapped to Transfer Controller 0,
244	 * event queue 1 to TC2, etc. So we are asking PRCM to power on specific
245	 * TC based on what event queue we need to initialize */
246	ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn);
247
248	/* Clear Event Missed Regs */
249	ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF);
250	ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 0xFFFFFFFF);
251	ti_edma3_cc_wr_4(TI_EDMA3CC_QEMCR, 0xFFFFFFFF);
252
253	/* Clear Error Reg */
254	ti_edma3_cc_wr_4(TI_EDMA3CC_CCERRCLR, 0xFFFFFFFF);
255
256	/* Enable DMA channels 0-63 */
257	ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), 0xFFFFFFFF);
258	ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), 0xFFFFFFFF);
259
260	for (i = 0; i < 64; i++) {
261		ti_edma3_cc_wr_4(TI_EDMA3CC_DCHMAP(i), i<<5);
262	}
263
264	/* Initialize the DMA Queue Number Registers */
265	for (i = 0; i < TI_EDMA3_NUM_DMA_CHS; i++) {
266		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(i>>3));
267		reg &= TI_EDMA3CC_DMAQNUM_CLR(i);
268		reg |= TI_EDMA3CC_DMAQNUM_SET(i, eqn);
269		ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(i>>3), reg);
270	}
271
272	/* Enable the QDMA Region access for all channels */
273	ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), (1 << TI_EDMA3_NUM_QDMA_CHS) - 1);
274
275	/*Initialize QDMA Queue Number Registers */
276	for (i = 0; i < TI_EDMA3_NUM_QDMA_CHS; i++) {
277		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
278		reg &= TI_EDMA3CC_QDMAQNUM_CLR(i);
279		reg |= TI_EDMA3CC_QDMAQNUM_SET(i, eqn);
280		ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
281	}
282}
283
284#ifdef notyet
285int
286ti_edma3_enable_event_intr(unsigned int ch)
287{
288	uint32_t reg;
289
290	if (ch >= TI_EDMA3_NUM_DMA_CHS)
291		return (EINVAL);
292
293	if (ch < 32) {
294		ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESR(0), 1 << ch);
295	} else {
296		ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESRH(0), 1 << (ch - 32));
297	}
298	return 0;
299}
300#endif
301
302int
303ti_edma3_request_dma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
304{
305	uint32_t reg;
306
307	if (ch >= TI_EDMA3_NUM_DMA_CHS)
308		return (EINVAL);
309
310	/* Enable the DMA channel in the DRAE/DRAEH registers */
311	if (ch < 32) {
312		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAE(0));
313		reg |= (0x01 << ch);
314		ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), reg);
315	} else {
316		reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAEH(0));
317		reg |= (0x01 << (ch - 32));
318		ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), reg);
319	}
320
321	/* Associate DMA Channel to Event Queue */
322	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(ch >> 3));
323	reg &= TI_EDMA3CC_DMAQNUM_CLR(ch);
324	reg |= TI_EDMA3CC_DMAQNUM_SET((ch), eqn);
325	ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(ch >> 3), reg);
326
327	/* Set TCC in corresponding PaRAM Entry */
328	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
329	reg &= TI_EDMA3CC_OPT_TCC_CLR;
330	reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
331	ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
332
333	return 0;
334}
335
336int
337ti_edma3_request_qdma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
338{
339	uint32_t reg;
340
341	if (ch >= TI_EDMA3_NUM_DMA_CHS)
342		return (EINVAL);
343
344	/* Enable the QDMA channel in the QRAE registers */
345	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QRAE(0));
346	reg |= (0x01 << ch);
347	ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), reg);
348
349	/* Associate QDMA Channel to Event Queue */
350	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
351	reg |= TI_EDMA3CC_QDMAQNUM_SET(ch, eqn);
352	ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
353
354	/* Set TCC in corresponding PaRAM Entry */
355	reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
356	reg &= TI_EDMA3CC_OPT_TCC_CLR;
357	reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
358	ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
359
360	return 0;
361}
362
363int
364ti_edma3_enable_transfer_manual(unsigned int ch)
365{
366	if (ch >= TI_EDMA3_NUM_DMA_CHS)
367		return (EINVAL);
368
369	/* set corresponding bit in ESR/ESRH to set a event */
370	if (ch < 32) {
371		ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESR(0), 1 <<  ch);
372	} else {
373		ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESRH(0), 1 <<  (ch - 32));
374	}
375
376	return 0;
377}
378
379int
380ti_edma3_enable_transfer_qdma(unsigned int ch)
381{
382	if (ch >= TI_EDMA3_NUM_QDMA_CHS)
383		return (EINVAL);
384
385	/* set corresponding bit in QEESR to enable QDMA event */
386	ti_edma3_cc_wr_4(TI_EDMA3CC_S_QEESR(0), (1 << ch));
387
388	return 0;
389}
390
391int
392ti_edma3_enable_transfer_event(unsigned int ch)
393{
394	if (ch >= TI_EDMA3_NUM_DMA_CHS)
395		return (EINVAL);
396
397	/* Clear SECR(H) & EMCR(H) to clean any previous NULL request
398	 * and set corresponding bit in EESR to enable DMA event */
399	if(ch < 32) {
400		ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECR(0), (1 << ch));
401		ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, (1 << ch));
402		ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESR(0), (1 << ch));
403	} else {
404		ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECRH(0), 1 << (ch - 32));
405		ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 1 << (ch - 32));
406		ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESRH(0), 1 << (ch - 32));
407	}
408
409	return 0;
410}
411
412void
413ti_edma3_param_write(unsigned int ch, struct ti_edma3cc_param_set *prs)
414{
415	bus_write_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
416	    (uint32_t *) prs, 8);
417}
418
419void
420ti_edma3_param_read(unsigned int ch, struct ti_edma3cc_param_set *prs)
421{
422	bus_read_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
423	    (uint32_t *) prs, 8);
424}
425