1 /* Blackfin Direct Memory Access (DMA) Controller model.
3 Copyright (C) 2010-2022 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
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.
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.
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/>. */
21 /* This must come before any other includes. */
27 #include "hw-device.h"
28 #include "dv-bfin_dma.h"
29 #include "dv-bfin_dmac.h"
33 /* This top portion matches common dv_bfin struct. */
35 struct hw
*dma_master
;
38 const char * const *pmap
;
39 unsigned int pmap_count
;
43 bfin_dmac_get_peer (struct hw
*dma
, bu16 pmap
)
46 struct bfin_dmac
*dmac
;
54 unsigned int chan_num
= dv_get_bus_num (dma
);
59 sprintf (peer
, "%s/bfin_dma@%u", hw_path (me
), chan_num
);
63 unsigned int idx
= pmap
>> 12;
64 if (idx
>= dmac
->pmap_count
)
65 hw_abort (me
, "Invalid DMA peripheral_map %#x", pmap
);
67 sprintf (peer
, "/core/bfin_%s", dmac
->pmap
[idx
]);
70 ret
= hw_tree_find_device (me
, peer
);
72 hw_abort (me
, "Unable to locate peer for %s (pmap:%#x %s)",
73 hw_name (dma
), pmap
, peer
);
78 bfin_dmac_default_pmap (struct hw
*dma
)
80 unsigned int chan_num
= dv_get_bus_num (dma
);
82 if (chan_num
< BFIN_DMAC_MDMA_BASE
)
83 return (chan_num
% 12) << 12;
85 return CTYPE
; /* MDMA */
88 static const char * const bfin_dmac_50x_pmap
[] =
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",
94 /* XXX: Need to figure out how to handle portmuxed DMA channels. */
95 static const struct hw_port_descriptor bfin_dmac_50x_ports
[] =
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
, },
112 static const char * const bfin_dmac_51x_pmap
[] =
114 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
115 "sport@1", "spi@0", "uart@0", "uart@0", "uart@1", "uart@1",
118 /* XXX: Need to figure out how to handle portmuxed DMA channels. */
119 static const struct hw_port_descriptor bfin_dmac_51x_ports
[] =
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
, },
138 static const char * const bfin_dmac_52x_pmap
[] =
140 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
141 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
144 /* XXX: Need to figure out how to handle portmuxed DMA channels
145 like PPI/NFC here which share DMA0. */
146 static const struct hw_port_descriptor bfin_dmac_52x_ports
[] =
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
, },
166 static const char * const bfin_dmac_533_pmap
[] =
168 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi",
172 static const struct hw_port_descriptor bfin_dmac_533_ports
[] =
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
, },
185 static const char * const bfin_dmac_537_pmap
[] =
187 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
188 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
191 static const struct hw_port_descriptor bfin_dmac_537_ports
[] =
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
, },
208 static const char * const bfin_dmac0_538_pmap
[] =
210 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
214 static const struct hw_port_descriptor bfin_dmac0_538_ports
[] =
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
, },
227 static const char * const bfin_dmac1_538_pmap
[] =
229 "sport@2", "sport@2", "sport@3", "sport@3", NULL
, NULL
,
230 "spi@1", "spi@2", "uart@1", "uart@1", "uart@2", "uart@2",
233 static const struct hw_port_descriptor bfin_dmac1_538_ports
[] =
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
, },
248 static const char * const bfin_dmac0_54x_pmap
[] =
250 "sport@0", "sport@0", "sport@1", "sport@1", "spi@0", "spi@1",
251 "uart2@0", "uart2@0", "uart2@1", "uart2@1", "atapi", "atapi",
254 static const struct hw_port_descriptor bfin_dmac0_54x_ports
[] =
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
, },
271 static const char * const bfin_dmac1_54x_pmap
[] =
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",
278 static const struct hw_port_descriptor bfin_dmac1_54x_ports
[] =
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
, },
300 static const char * const bfin_dmac0_561_pmap
[] =
302 "sport@0", "sport@0", "sport@1", "sport@1", "spi", "uart@0", "uart@0",
305 static const struct hw_port_descriptor bfin_dmac0_561_ports
[] =
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
, },
317 static const char * const bfin_dmac1_561_pmap
[] =
322 static const struct hw_port_descriptor bfin_dmac1_561_ports
[] =
324 { "ppi@0", 0, 0, input_port
, },
325 { "ppi@1", 1, 0, input_port
, },
329 static const char * const bfin_dmac_59x_pmap
[] =
331 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
332 "spi@1", "uart@0", "uart@0",
335 static const struct hw_port_descriptor bfin_dmac_59x_ports
[] =
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
, },
350 bfin_dmac_port_event (struct hw
*me
, int my_port
, struct hw
*source
,
351 int source_port
, int level
)
353 SIM_DESC sd
= hw_system (me
);
354 struct bfin_dmac
*dmac
= hw_data (me
);
355 struct hw
*dma
= hw_child (me
);
360 sim_hw_io_read_buffer (sd
, dma
, &pmap
, 0, 0x2c, sizeof (pmap
));
364 dma
= hw_sibling (dma
);
368 hw_abort (me
, "no valid dma mapping found for %s", dmac
->pmap
[my_port
]);
370 /* Have the DMA channel raise its interrupt to the SIC. */
371 hw_port_event (dma
, 0, 1);
375 bfin_dmac_finish (struct hw
*me
)
377 struct bfin_dmac
*dmac
;
378 unsigned int dmac_num
= dv_get_bus_num (me
);
380 dmac
= HW_ZALLOC (me
, struct bfin_dmac
);
382 set_hw_data (me
, dmac
);
383 set_hw_port_event (me
, bfin_dmac_port_event
);
385 /* Initialize the DMA Controller. */
386 if (hw_find_property (me
, "type") == NULL
)
387 hw_abort (me
, "Missing \"type\" property");
389 switch (hw_find_integer_property (me
, "type"))
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
);
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
);
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
);
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
);
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
);
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
);
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
);
442 hw_abort (me
, "this Blackfin only has a DMAC0 & DMAC1");
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
);
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
);
459 hw_abort (me
, "this Blackfin only has a DMAC0 & DMAC1");
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
);
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
);
476 hw_abort (me
, "this Blackfin only has a DMAC0 & DMAC1");
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
);
487 hw_abort (me
, "no support for DMAC on this Blackfin model yet");
491 const struct hw_descriptor dv_bfin_dmac_descriptor
[] =
493 {"bfin_dmac", bfin_dmac_finish
,},