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