Update copyright year range in all GDB files.
[deliverable/binutils-gdb.git] / sim / bfin / dv-bfin_dmac.c
CommitLineData
ef016f83
MF
1/* Blackfin Direct Memory Access (DMA) Controller model.
2
b811d2c2 3 Copyright (C) 2010-2020 Free Software Foundation, Inc.
ef016f83
MF
4 Contributed by Analog Devices, Inc.
5
6 This file is part of simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22
23#include "sim-main.h"
24#include "sim-hw.h"
25#include "devices.h"
26#include "hw-device.h"
27#include "dv-bfin_dma.h"
28#include "dv-bfin_dmac.h"
29
30struct bfin_dmac
31{
32 /* This top portion matches common dv_bfin struct. */
33 bu32 base;
34 struct hw *dma_master;
35 bool acked;
36
2613074f 37 const char * const *pmap;
ef016f83
MF
38 unsigned int pmap_count;
39};
40
41struct hw *
42bfin_dmac_get_peer (struct hw *dma, bu16 pmap)
43{
44 struct hw *ret, *me;
45 struct bfin_dmac *dmac;
46 char peer[100];
47
48 me = hw_parent (dma);
49 dmac = hw_data (me);
50 if (pmap & CTYPE)
51 {
52 /* MDMA channel. */
53 unsigned int chan_num = dv_get_bus_num (dma);
54 if (chan_num & 1)
55 chan_num &= ~1;
56 else
57 chan_num |= 1;
58 sprintf (peer, "%s/bfin_dma@%u", hw_path (me), chan_num);
59 }
60 else
61 {
62 unsigned int idx = pmap >> 12;
63 if (idx >= dmac->pmap_count)
64 hw_abort (me, "Invalid DMA peripheral_map %#x", pmap);
65 else
66 sprintf (peer, "/core/bfin_%s", dmac->pmap[idx]);
67 }
68
69 ret = hw_tree_find_device (me, peer);
70 if (!ret)
71 hw_abort (me, "Unable to locate peer for %s (pmap:%#x %s)",
72 hw_name (dma), pmap, peer);
73 return ret;
74}
75
76bu16
77bfin_dmac_default_pmap (struct hw *dma)
78{
79 unsigned int chan_num = dv_get_bus_num (dma);
80
81 if (chan_num < BFIN_DMAC_MDMA_BASE)
82 return (chan_num % 12) << 12;
83 else
84 return CTYPE; /* MDMA */
85}
86
2613074f 87static const char * const bfin_dmac_50x_pmap[] =
990d19fd 88{
ef016f83
MF
89 "ppi@0", "rsi", "sport@0", "sport@0", "sport@1", "sport@1",
90 "spi@0", "spi@1", "uart2@0", "uart2@0", "uart2@1", "uart2@1",
91};
92
93/* XXX: Need to figure out how to handle portmuxed DMA channels. */
990d19fd
MF
94static const struct hw_port_descriptor bfin_dmac_50x_ports[] =
95{
ef016f83
MF
96 { "ppi@0", 0, 0, input_port, },
97 { "rsi", 1, 0, input_port, },
98 { "sport@0_rx", 2, 0, input_port, },
99 { "sport@0_tx", 3, 0, input_port, },
100 { "sport@1_tx", 4, 0, input_port, },
101 { "sport@1_rx", 5, 0, input_port, },
102 { "spi@0", 6, 0, input_port, },
103 { "spi@1", 7, 0, input_port, },
104 { "uart2@0_rx", 8, 0, input_port, },
105 { "uart2@0_tx", 9, 0, input_port, },
106 { "uart2@1_rx", 10, 0, input_port, },
107 { "uart2@1_tx", 11, 0, input_port, },
108 { NULL, 0, 0, 0, },
109};
110
2613074f 111static const char * const bfin_dmac_51x_pmap[] =
990d19fd 112{
ef016f83
MF
113 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
114 "sport@1", "spi@0", "uart@0", "uart@0", "uart@1", "uart@1",
115};
116
117/* XXX: Need to figure out how to handle portmuxed DMA channels. */
990d19fd
MF
118static const struct hw_port_descriptor bfin_dmac_51x_ports[] =
119{
ef016f83
MF
120 { "ppi@0", 0, 0, input_port, },
121 { "emac_rx", 1, 0, input_port, },
122 { "emac_tx", 2, 0, input_port, },
123 { "sport@0_rx", 3, 0, input_port, },
124 { "sport@0_tx", 4, 0, input_port, },
125/*{ "rsi", 4, 0, input_port, },*/
126 { "sport@1_tx", 5, 0, input_port, },
127/*{ "spi@1", 5, 0, input_port, },*/
128 { "sport@1_rx", 6, 0, input_port, },
129 { "spi@0", 7, 0, input_port, },
130 { "uart@0_rx", 8, 0, input_port, },
131 { "uart@0_tx", 9, 0, input_port, },
132 { "uart@1_rx", 10, 0, input_port, },
133 { "uart@1_tx", 11, 0, input_port, },
134 { NULL, 0, 0, 0, },
135};
136
2613074f 137static const char * const bfin_dmac_52x_pmap[] =
990d19fd 138{
ef016f83
MF
139 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
140 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
141};
142
143/* XXX: Need to figure out how to handle portmuxed DMA channels
144 like PPI/NFC here which share DMA0. */
990d19fd
MF
145static const struct hw_port_descriptor bfin_dmac_52x_ports[] =
146{
ef016f83
MF
147 { "ppi@0", 0, 0, input_port, },
148/*{ "nfc", 0, 0, input_port, },*/
149 { "emac_rx", 1, 0, input_port, },
150/*{ "hostdp", 1, 0, input_port, },*/
151 { "emac_tx", 2, 0, input_port, },
152/*{ "nfc", 2, 0, input_port, },*/
153 { "sport@0_tx", 3, 0, input_port, },
154 { "sport@0_rx", 4, 0, input_port, },
155 { "sport@1_tx", 5, 0, input_port, },
156 { "sport@1_rx", 6, 0, input_port, },
157 { "spi", 7, 0, input_port, },
158 { "uart@0_tx", 8, 0, input_port, },
159 { "uart@0_rx", 9, 0, input_port, },
160 { "uart@1_tx", 10, 0, input_port, },
161 { "uart@1_rx", 11, 0, input_port, },
162 { NULL, 0, 0, 0, },
163};
164
2613074f 165static const char * const bfin_dmac_533_pmap[] =
990d19fd 166{
ef016f83
MF
167 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi",
168 "uart@0", "uart@0",
169};
170
990d19fd
MF
171static const struct hw_port_descriptor bfin_dmac_533_ports[] =
172{
ef016f83
MF
173 { "ppi@0", 0, 0, input_port, },
174 { "sport@0_tx", 1, 0, input_port, },
175 { "sport@0_rx", 2, 0, input_port, },
176 { "sport@1_tx", 3, 0, input_port, },
177 { "sport@1_rx", 4, 0, input_port, },
178 { "spi", 5, 0, input_port, },
179 { "uart@0_tx", 6, 0, input_port, },
180 { "uart@0_rx", 7, 0, input_port, },
181 { NULL, 0, 0, 0, },
182};
183
2613074f 184static const char * const bfin_dmac_537_pmap[] =
990d19fd 185{
ef016f83
MF
186 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
187 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
188};
189
990d19fd
MF
190static const struct hw_port_descriptor bfin_dmac_537_ports[] =
191{
ef016f83
MF
192 { "ppi@0", 0, 0, input_port, },
193 { "emac_rx", 1, 0, input_port, },
194 { "emac_tx", 2, 0, input_port, },
195 { "sport@0_tx", 3, 0, input_port, },
196 { "sport@0_rx", 4, 0, input_port, },
197 { "sport@1_tx", 5, 0, input_port, },
198 { "sport@1_rx", 6, 0, input_port, },
199 { "spi", 7, 0, input_port, },
200 { "uart@0_tx", 8, 0, input_port, },
201 { "uart@0_rx", 9, 0, input_port, },
202 { "uart@1_tx", 10, 0, input_port, },
203 { "uart@1_rx", 11, 0, input_port, },
204 { NULL, 0, 0, 0, },
205};
206
2613074f 207static const char * const bfin_dmac0_538_pmap[] =
990d19fd 208{
ef016f83
MF
209 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
210 "uart@0", "uart@0",
211};
212
990d19fd
MF
213static const struct hw_port_descriptor bfin_dmac0_538_ports[] =
214{
ef016f83
MF
215 { "ppi@0", 0, 0, input_port, },
216 { "sport@0_rx", 1, 0, input_port, },
217 { "sport@0_tx", 2, 0, input_port, },
218 { "sport@1_rx", 3, 0, input_port, },
219 { "sport@1_tx", 4, 0, input_port, },
220 { "spi@0", 5, 0, input_port, },
221 { "uart@0_rx", 6, 0, input_port, },
222 { "uart@0_tx", 7, 0, input_port, },
223 { NULL, 0, 0, 0, },
224};
225
2613074f 226static const char * const bfin_dmac1_538_pmap[] =
990d19fd 227{
ef016f83
MF
228 "sport@2", "sport@2", "sport@3", "sport@3", NULL, NULL,
229 "spi@1", "spi@2", "uart@1", "uart@1", "uart@2", "uart@2",
230};
231
990d19fd
MF
232static const struct hw_port_descriptor bfin_dmac1_538_ports[] =
233{
ef016f83
MF
234 { "sport@2_rx", 0, 0, input_port, },
235 { "sport@2_tx", 1, 0, input_port, },
236 { "sport@3_rx", 2, 0, input_port, },
237 { "sport@3_tx", 3, 0, input_port, },
238 { "spi@1", 6, 0, input_port, },
239 { "spi@2", 7, 0, input_port, },
240 { "uart@1_rx", 8, 0, input_port, },
241 { "uart@1_tx", 9, 0, input_port, },
242 { "uart@2_rx", 10, 0, input_port, },
243 { "uart@2_tx", 11, 0, input_port, },
244 { NULL, 0, 0, 0, },
245};
246
2613074f 247static const char * const bfin_dmac0_54x_pmap[] =
990d19fd 248{
ef016f83
MF
249 "sport@0", "sport@0", "sport@1", "sport@1", "spi@0", "spi@1",
250 "uart2@0", "uart2@0", "uart2@1", "uart2@1", "atapi", "atapi",
251};
252
990d19fd
MF
253static const struct hw_port_descriptor bfin_dmac0_54x_ports[] =
254{
ef016f83
MF
255 { "sport@0_rx", 0, 0, input_port, },
256 { "sport@0_tx", 1, 0, input_port, },
257 { "sport@1_rx", 2, 0, input_port, },
258 { "sport@1_tx", 3, 0, input_port, },
259 { "spi@0", 4, 0, input_port, },
260 { "spi@1", 5, 0, input_port, },
261 { "uart2@0_rx", 6, 0, input_port, },
262 { "uart2@0_tx", 7, 0, input_port, },
263 { "uart2@1_rx", 8, 0, input_port, },
264 { "uart2@1_tx", 9, 0, input_port, },
265 { "atapi", 10, 0, input_port, },
266 { "atapi", 11, 0, input_port, },
267 { NULL, 0, 0, 0, },
268};
269
2613074f 270static const char * const bfin_dmac1_54x_pmap[] =
990d19fd 271{
ef016f83
MF
272 "eppi@0", "eppi@1", "eppi@2", "pixc", "pixc", "pixc",
273 "sport@2", "sport@2", "sport@3", "sport@3", "sdh",
274 "spi@2", "uart2@2", "uart2@2", "uart2@3", "uart2@3",
275};
276
990d19fd
MF
277static const struct hw_port_descriptor bfin_dmac1_54x_ports[] =
278{
ef016f83
MF
279 { "eppi@0", 0, 0, input_port, },
280 { "eppi@1", 1, 0, input_port, },
281 { "eppi@2", 2, 0, input_port, },
282 { "pixc", 3, 0, input_port, },
283 { "pixc", 4, 0, input_port, },
284 { "pixc", 5, 0, input_port, },
285 { "sport@2_rx", 6, 0, input_port, },
286 { "sport@2_tx", 7, 0, input_port, },
287 { "sport@3_rx", 8, 0, input_port, },
288 { "sport@3_tx", 9, 0, input_port, },
289 { "sdh", 10, 0, input_port, },
290/*{ "nfc", 10, 0, input_port, },*/
291 { "spi@2", 11, 0, input_port, },
292 { "uart2@2_rx", 12, 0, input_port, },
293 { "uart2@2_tx", 13, 0, input_port, },
294 { "uart2@3_rx", 14, 0, input_port, },
295 { "uart2@3_tx", 15, 0, input_port, },
296 { NULL, 0, 0, 0, },
297};
298
2613074f 299static const char * const bfin_dmac0_561_pmap[] =
990d19fd 300{
ef016f83
MF
301 "sport@0", "sport@0", "sport@1", "sport@1", "spi", "uart@0", "uart@0",
302};
303
990d19fd
MF
304static const struct hw_port_descriptor bfin_dmac0_561_ports[] =
305{
ef016f83
MF
306 { "sport@0_rx", 0, 0, input_port, },
307 { "sport@0_tx", 1, 0, input_port, },
308 { "sport@1_rx", 2, 0, input_port, },
309 { "sport@1_tx", 3, 0, input_port, },
310 { "spi@0", 4, 0, input_port, },
311 { "uart@0_rx", 5, 0, input_port, },
312 { "uart@0_tx", 6, 0, input_port, },
313 { NULL, 0, 0, 0, },
314};
315
2613074f 316static const char * const bfin_dmac1_561_pmap[] =
990d19fd 317{
ef016f83
MF
318 "ppi@0", "ppi@1",
319};
320
990d19fd
MF
321static const struct hw_port_descriptor bfin_dmac1_561_ports[] =
322{
ef016f83
MF
323 { "ppi@0", 0, 0, input_port, },
324 { "ppi@1", 1, 0, input_port, },
325 { NULL, 0, 0, 0, },
326};
327
2613074f 328static const char * const bfin_dmac_59x_pmap[] =
990d19fd 329{
ef016f83
MF
330 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
331 "spi@1", "uart@0", "uart@0",
332};
333
990d19fd
MF
334static const struct hw_port_descriptor bfin_dmac_59x_ports[] =
335{
ef016f83
MF
336 { "ppi@0", 0, 0, input_port, },
337 { "sport@0_tx", 1, 0, input_port, },
338 { "sport@0_rx", 2, 0, input_port, },
339 { "sport@1_tx", 3, 0, input_port, },
340 { "sport@1_rx", 4, 0, input_port, },
341 { "spi@0", 5, 0, input_port, },
342 { "spi@1", 6, 0, input_port, },
343 { "uart@0_rx", 7, 0, input_port, },
344 { "uart@0_tx", 8, 0, input_port, },
345 { NULL, 0, 0, 0, },
346};
347
348static void
349bfin_dmac_port_event (struct hw *me, int my_port, struct hw *source,
350 int source_port, int level)
351{
352 SIM_DESC sd = hw_system (me);
353 struct bfin_dmac *dmac = hw_data (me);
354 struct hw *dma = hw_child (me);
355
356 while (dma)
357 {
358 bu16 pmap;
359 sim_hw_io_read_buffer (sd, dma, &pmap, 0, 0x2c, sizeof (pmap));
360 pmap >>= 12;
361 if (pmap == my_port)
362 break;
363 dma = hw_sibling (dma);
364 }
365
366 if (!dma)
367 hw_abort (me, "no valid dma mapping found for %s", dmac->pmap[my_port]);
368
369 /* Have the DMA channel raise its interrupt to the SIC. */
370 hw_port_event (dma, 0, 1);
371}
372
373static void
374bfin_dmac_finish (struct hw *me)
375{
376 struct bfin_dmac *dmac;
377 unsigned int dmac_num = dv_get_bus_num (me);
378
379 dmac = HW_ZALLOC (me, struct bfin_dmac);
380
381 set_hw_data (me, dmac);
382 set_hw_port_event (me, bfin_dmac_port_event);
383
384 /* Initialize the DMA Controller. */
385 if (hw_find_property (me, "type") == NULL)
386 hw_abort (me, "Missing \"type\" property");
387
388 switch (hw_find_integer_property (me, "type"))
389 {
390 case 500 ... 509:
391 if (dmac_num != 0)
392 hw_abort (me, "this Blackfin only has a DMAC0");
393 dmac->pmap = bfin_dmac_50x_pmap;
394 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_50x_pmap);
395 set_hw_ports (me, bfin_dmac_50x_ports);
396 break;
397 case 510 ... 519:
398 if (dmac_num != 0)
399 hw_abort (me, "this Blackfin only has a DMAC0");
400 dmac->pmap = bfin_dmac_51x_pmap;
401 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_51x_pmap);
402 set_hw_ports (me, bfin_dmac_51x_ports);
403 break;
404 case 522 ... 527:
405 if (dmac_num != 0)
406 hw_abort (me, "this Blackfin only has a DMAC0");
407 dmac->pmap = bfin_dmac_52x_pmap;
408 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_52x_pmap);
409 set_hw_ports (me, bfin_dmac_52x_ports);
410 break;
411 case 531 ... 533:
412 if (dmac_num != 0)
413 hw_abort (me, "this Blackfin only has a DMAC0");
414 dmac->pmap = bfin_dmac_533_pmap;
415 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_533_pmap);
416 set_hw_ports (me, bfin_dmac_533_ports);
417 break;
418 case 534:
419 case 536:
420 case 537:
421 if (dmac_num != 0)
422 hw_abort (me, "this Blackfin only has a DMAC0");
423 dmac->pmap = bfin_dmac_537_pmap;
424 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_537_pmap);
425 set_hw_ports (me, bfin_dmac_537_ports);
426 break;
427 case 538 ... 539:
428 switch (dmac_num)
429 {
430 case 0:
431 dmac->pmap = bfin_dmac0_538_pmap;
432 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_538_pmap);
433 set_hw_ports (me, bfin_dmac0_538_ports);
434 break;
435 case 1:
436 dmac->pmap = bfin_dmac1_538_pmap;
437 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_538_pmap);
438 set_hw_ports (me, bfin_dmac1_538_ports);
439 break;
440 default:
441 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
442 }
443 break;
444 case 540 ... 549:
445 switch (dmac_num)
446 {
447 case 0:
448 dmac->pmap = bfin_dmac0_54x_pmap;
449 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_54x_pmap);
450 set_hw_ports (me, bfin_dmac0_54x_ports);
451 break;
452 case 1:
453 dmac->pmap = bfin_dmac1_54x_pmap;
454 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_54x_pmap);
455 set_hw_ports (me, bfin_dmac1_54x_ports);
456 break;
457 default:
458 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
459 }
460 break;
461 case 561:
462 switch (dmac_num)
463 {
464 case 0:
465 dmac->pmap = bfin_dmac0_561_pmap;
466 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_561_pmap);
467 set_hw_ports (me, bfin_dmac0_561_ports);
468 break;
469 case 1:
470 dmac->pmap = bfin_dmac1_561_pmap;
471 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_561_pmap);
472 set_hw_ports (me, bfin_dmac1_561_ports);
473 break;
474 default:
475 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
476 }
477 break;
478 case 590 ... 599:
479 if (dmac_num != 0)
480 hw_abort (me, "this Blackfin only has a DMAC0");
481 dmac->pmap = bfin_dmac_59x_pmap;
482 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_59x_pmap);
483 set_hw_ports (me, bfin_dmac_59x_ports);
484 break;
485 default:
486 hw_abort (me, "no support for DMAC on this Blackfin model yet");
487 }
488}
489
81d126c3
MF
490const struct hw_descriptor dv_bfin_dmac_descriptor[] =
491{
ef016f83
MF
492 {"bfin_dmac", bfin_dmac_finish,},
493 {NULL, NULL},
494};
This page took 0.488815 seconds and 4 git commands to generate.