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